diff --git a/.gitignore b/.gitignore index 59ec847b..813d6c10 100644 --- a/.gitignore +++ b/.gitignore @@ -2,11 +2,9 @@ .DS_Store *.swp *.tmp -*~ # Project files that should not be in the repo .* -\#* !/.gitignore .*.gz *.tmTheme.js diff --git a/.gitmodules b/.gitmodules index 07bbe371..4678c516 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "doc/wiki"] path = doc/wiki - url = https://github.com/ajaxorg/ace.wiki.git + url = git://github.com/ajaxorg/ace.wiki.git [submodule "build"] path = build - url = https://github.com/ajaxorg/ace-builds.git + url = git://github.com/ajaxorg/ace-builds.git diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 062af59c..c44edcb0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,9 +7,16 @@ 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://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. +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 -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. +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. -Happy coding, Cloud9 +Email: ace+cla@c9.io + +Fax: +31 (0) 206388953 + +Address: Ajax.org B.V. + Keizersgracht 241 + 1016 EA, Amsterdam + the Netherlands \ No newline at end of file diff --git a/ChangeLog.txt b/ChangeLog.txt index 3077d171..d4f5e1d1 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,103 +1,4 @@ -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 - - `editor.commands.commandKeyBinding` now contains direct map from keys to commands instead of grouping them by hashid - -* New Features - - Improved autoindent for html and php modes (Adam Jimenez) - - Find All from searchbox (Colton Voege) - -* new language modes - - Elixir, Elm - -2014.09.21 Version 1.1.7 - -* Bugfixes - - fix several bugs in autocompletion - - workaround for inaccurate getBoundingClientRect on chrome 37 - -2014.08.17 Version 1.1.6 - -* Bugfixes - - fix regression in double tap to highlight - - Improved Latex Mode (Daniel Felder) - -* API Changes - - editor.destroy destroys editor.session too (call editor.setSession(null) to prevent that) - -* new language modes - - Praat (José Joaquín Atria) - - Eiffel (Victorien Elvinger) - - G-code (Adam Joseph Cook) - -2014.07.09 Version 1.1.5 - -* Bugfixes - - fix regression in autocomplete popup - -* new language modes - - gitignore (Devon Carew) - -2014.07.01 Version 1.1.4 - -* New Features - - Highlight matching tags (Adam Jimenez) - - Improved jump to matching command (Adam Jimenez) - -* new language modes - - AppleScript (Yaogang Lian) - - Vala - -2014.03.08 Version 1.1.3 - -* New Features - - Allow syntax checkers to be loaded from CDN (Derk-Jan Hartman) - - Add ColdFusion behavior (Abram Adams) - - add showLineNumbers option - - Add html syntax checker (danyaPostfactum) - -* new language modes - - Gherkin (Patrick Nevels) - - Smarty - -2013.12.02 Version 1.1.2 - -* New Features - - Accessibility Theme for Ace (Peter Xiao) - - use snipetManager for expanding emmet snippets - - update jshint to 2.1.4 - - improve php syntax checker (jdalegonzalez) - - add option for autoresizing - - add option for autohiding vertical scrollbar - - improvements to highlighting of xml like languages (danyaPostfactum) - - add support for autocompletion and snippets (gjtorikyan danyaPostfactum and others) - - add option to merge similar changes in undo history - - add scrollPastEnd option - - use html5 dragndrop for text dragging (danyaPostfactum) - -* API Changes - - fixed typo in HashHandler commmandManager - -* new language modes - - Nix (Zef Hemel) - - Protobuf (Zef Hemel) - - Soy - - Handlebars - -2013.06.04 Version 1.1.1 +2013.06.04 Version 1.1.01 - Improved emacs keybindings (Robert Krahn) - Added markClean, isClean methods to UndoManager (Joonsoo Jeon) diff --git a/Makefile b/Makefile index 29cf0495..95dcf964 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ pre_build: build: pre_build ./Makefile.dryice.js normal ./Makefile.dryice.js demo + ./Makefile.dryice.js bm # Minimal build: call Makefile.dryice.js only if our sources changed basic: build/src/ace.js diff --git a/Makefile.dryice.js b/Makefile.dryice.js index 0ce7c657..14ffea23 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -31,23 +31,22 @@ var fs = require("fs"); var path = require("path"); -var copy = require('architect-build/copy'); -var build = require('architect-build/build'); +if (!fs.existsSync) + fs.existsSync = path.existsSync; +else + path.existsSync = fs.existsSync; +var copy = require('dryice').copy; var ACE_HOME = __dirname; var BUILD_DIR = ACE_HOME + "/build"; -var CACHE = {}; function main(args) { - if (args.indexOf("updateModes") !== -1) { - return updateModes(); - } var type = "minimal"; args = args.map(function(x) { if (x[0] == "-" && x[1] != "-") return "-" + x; return x; - }).filter(Boolean); + }); if (args[2] && (args[2][0] != "-" || args[2].indexOf("h") != -1)) type = args[2]; @@ -67,24 +66,22 @@ function main(args) { ace(); } else if (type == "demo") { demo(); + } else if (type == "bm") { + bookmarklet(); } else if (type == "full") { - ace(); - demo(); - } else if (type == "highlighter") { - // TODO + demo(ace()); + bookmarklet(); } } -} -function showHelp(type) { console.log("--- Ace Dryice Build Tool ---"); console.log(""); console.log("Options:"); - console.log(" minimal Places necessary Ace files out in build dir; uses configuration flags below [default]"); - console.log(" normal Runs four Ace builds--minimal, minimal-noconflict, minimal-min, and minimal-noconflict-min"); - console.log(" demo Runs demo build of Ace"); - console.log(" full all of above"); - console.log(" highlighter "); + console.log(" minimal Places necessary Ace files out in build dir; uses configuration flags below [default]"); + console.log(" normal Runs four Ace builds--minimal, minimal-noconflict, minimal-min, and minimal-noconflict-min"); + console.log(" demo Runs demo build of Ace"); + console.log(" bm Runs bookmarklet build of Ace"); + console.log(" full all of above"); console.log("args:"); console.log(" --target ./path path to build folder"); console.log("flags:"); @@ -93,34 +90,94 @@ function showHelp(type) { console.log(" --nc namespace require"); console.log(" --s shrinkwrap (combines all output files into one)"); console.log(""); - if (type) - console.log(" output for " + type + " generated in " + BUILD_DIR); + if (BUILD_DIR) + console.log(" output generated in " + type + __dirname + "/" + BUILD_DIR) +} + +function bookmarklet() { + var targetDir = BUILD_DIR + "/textarea"; + copy({ + source: "build_support/editor_textarea.html", + dest: targetDir + '/editor.html' + }); + copy({ + source: "build_support/style.css", + dest: targetDir + '/style.css' + }); + + buildAce({ + targetDir: targetDir + "/src", + ns: "__ace_shadowed__", + exportModule: "ace/ext/textarea", + compress: false, + noconflict: true, + suffix: "", + name: "ace-bookmarklet", + workers: [], + keybindings: [] + }); } function ace() { + console.log('# ace ---------'); + + // uncompressed + var project = buildAce({ + compress: false, + noconflict: false + }); + buildAce({ + compress: false, + noconflict: true + }); + + // compressed + buildAce({ + compress: true, + noconflict: false + }); + buildAce({ + compress: true, + noconflict: true + }); + console.log('# ace License | Readme | Changelog ---------'); - copy.file(ACE_HOME + "/build_support/editor.html", BUILD_DIR + "/editor.html"); - copy.file(ACE_HOME + "/LICENSE", BUILD_DIR + "/LICENSE"); - copy.file(ACE_HOME + "/ChangeLog.txt", BUILD_DIR + "/ChangeLog.txt"); - - console.log('# ace ---------'); - for (var i = 0; i < 4; i++) - buildAce({compress: i & 2, noconflict: i & 1}); + copy({ + source: ACE_HOME + "/build_support/editor.html", + dest: BUILD_DIR + "/editor.html" + }); + copy({ + source: ACE_HOME + "/LICENSE", + dest: BUILD_DIR + "/LICENSE" + }); + copy({ + source: ACE_HOME + "/ChangeLog.txt", + dest: BUILD_DIR + "/ChangeLog.txt" + }); + + return project; } -function demo() { +function demo(project) { + project = project || buildAce({ + compress: false, + noconflict: false, + coreOnly: true + }); console.log('# kitchen sink ---------'); - var version = "", ref = ""; + var version, ref; try { version = JSON.parse(fs.readFileSync(ACE_HOME + "/package.json")).version; ref = fs.readFileSync(ACE_HOME + "/.git-ref").toString(); - } catch(e) {} + } catch(e) { + ref = ""; + version = ""; + } function changeComments(data) { return (data - .replace("doc/site/images/ace-logo.png", "demo/kitchen-sink/ace-logo.png") .replace(//g, "") .replace(/PACKAGE\-\->|")} - function script(str) {result.push('')} - scripts.forEach(function(s) { - s = s.replace(/"/g, ""); - if (s == "ace/ace") { - comment("load ace"); - script("ace"); - } else { - var extName = s.match(/[^/]*$/)[0]; - comment("load ace " + extName + " extension"); - script("ext-" + extName); - } - }); - result.push("
- + \ No newline at end of file diff --git a/build b/build index a4e495d8..8f2423d1 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit a4e495d8901876c6bafe3870a35cb8e32c827e97 +Subproject commit 8f2423d10a7cc5680dcdb42a2dd57d9b192e3b34 diff --git a/build_support/editor.html b/build_support/editor.html index 1d972cf9..06a4651b 100644 --- a/build_support/editor.html +++ b/build_support/editor.html @@ -8,8 +8,8 @@ body { overflow: hidden; } - - #editor { + + #editor { margin: 0; position: absolute; top: 0; @@ -27,7 +27,7 @@ alert("Ace Rocks " + items[i]); } } - + diff --git a/demo/autoresize.html b/demo/autoresize.html index b0464ecd..cc1dc5e3 100644 --- a/demo/autoresize.html +++ b/demo/autoresize.html @@ -7,62 +7,42 @@ -
autoresizing editor
+
autoresizing editor
minHeight = 2 lines
-
-

-
-

 
-
+
 
 
-
-
 
 
diff --git a/demo/emmet.html b/demo/emmet.html
index bd0d4abe..57f13f67 100644
--- a/demo/emmet.html
+++ b/demo/emmet.html
@@ -22,20 +22,19 @@
 
 

 
-
-
-
-
+
+
+
+
+
+
 
 
 
diff --git a/demo/ie7.html b/demo/ie7.html
index f5db8667..3a525f86 100644
--- a/demo/ie7.html
+++ b/demo/ie7.html
@@ -5,7 +5,7 @@
   
   ACE Editor StatusBar Demo
   
-
-
-
-

Client Side Syntax Highlighting

- -

Syntax highlighting using Ace language modes and themes.

- -
-.code { - width: 50%; - white-space: pre-wrap; - border: solid lightgrey 1px -} - -
- -
-function wobble (flam) {
-    return flam.wobbled = true;
-}
-
-
- - -
---[[-- -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 - -
- - - - - - - diff --git a/demo/static-highlighter/client-noconflict.html b/demo/static-highlighter/client-noconflict.html new file mode 100644 index 00000000..fa9d345d --- /dev/null +++ b/demo/static-highlighter/client-noconflict.html @@ -0,0 +1,71 @@ + + + + + Static Code highlighter using Ace + + + + + +

Client Side Syntax Highlighting

+ +

Syntax highlighting using Ace language modes and themes.

+ +
+.code { + width: 50%; + position: relative; + white-space: pre-wrap; +} + +
+ +
+function wobble (flam) {
+    return flam.wobbled = true;
+}
+
+// the scrollbars are from overflow auto on .ace_editor.
+
+
+ + + + + + + + diff --git a/demo/static-highlighter/server.js b/demo/static-highlighter/server.js index ea8361d4..d1d6adbb 100644 --- a/demo/static-highlighter/server.js +++ b/demo/static-highlighter/server.js @@ -2,13 +2,15 @@ * 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"); @@ -18,22 +20,15 @@ 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(path, "utf8", function(err, data) { - if (err) data = err.message; + fs.readFile(__filename, "utf8", function(err, data) { var highlighted = highlighter.render(data, new JavaScriptMode(), theme); res.end( '\n' + '\n' + - highlighted.html + + highlighted.html + '' ); }); diff --git a/demo/statusbar.html b/demo/statusbar.html index d38bfcb9..47341d3b 100644 --- a/demo/statusbar.html +++ b/demo/statusbar.html @@ -41,19 +41,15 @@

 
ace rocks!
- + + diff --git a/doc/Contributor_License_Agreement-v2.pdf b/doc/Contributor_License_Agreement-v2.pdf new file mode 100644 index 00000000..1c4baa87 Binary files /dev/null and b/doc/Contributor_License_Agreement-v2.pdf differ diff --git a/doc/Corporate_Contributor_License_Agreement-v2.pdf b/doc/Corporate_Contributor_License_Agreement-v2.pdf new file mode 100644 index 00000000..dbeaf37c Binary files /dev/null and b/doc/Corporate_Contributor_License_Agreement-v2.pdf differ diff --git a/doc/site/images/FineCut_small_logo.png b/doc/site/images/FineCut_small_logo.png new file mode 100644 index 00000000..87f310b2 Binary files /dev/null and b/doc/site/images/FineCut_small_logo.png differ diff --git a/doc/site/images/KERA-med-web.png b/doc/site/images/KERA-med-web.png new file mode 100644 index 00000000..de004afc Binary files /dev/null and b/doc/site/images/KERA-med-web.png differ diff --git a/doc/site/images/acebug-logo.png b/doc/site/images/acebug-logo.png new file mode 100644 index 00000000..cac5a3fb Binary files /dev/null and b/doc/site/images/acebug-logo.png differ diff --git a/doc/site/images/lws-logo.png b/doc/site/images/lws-logo.png new file mode 100644 index 00000000..402b332c Binary files /dev/null and b/doc/site/images/lws-logo.png differ diff --git a/doc/site/js/main.js b/doc/site/js/main.js index 39dc202d..ed9fbff4 100644 --- a/doc/site/js/main.js +++ b/doc/site/js/main.js @@ -1,62 +1,49 @@ var editor; var embedded_editor; $(function() { - if (typeof ace !== "undefined") { - ace.config.set("workerPath", "build/src-min"); - editor = ace.edit("ace_editor_demo"); - editor.container.style.opacity = ""; - embedded_editor = ace.edit("embedded_ace_code"); - embedded_editor.container.style.opacity = ""; - embedded_editor.session.setMode("ace/mode/html"); - embedded_editor.setAutoScrollEditorIntoView(true); - embedded_editor.setOption("maxLines", 40); - - editor.setOptions({ - maxLines: 30, - mode: "ace/mode/javascript", - autoScrollEditorIntoView: true + ace.config.set("workerPath", "build/src-min"); + editor = ace.edit("ace_editor_demo"); + editor.container.style.opacity = ""; + embedded_editor = ace.edit("embedded_ace_code"); + embedded_editor.container.style.opacity = ""; + editor.session.setMode("ace/mode/javascript"); + editor.session.setMode("ace/mode/javascript"); + embedded_editor.session.setMode("ace/mode/html"); + + ace.config.loadModule("ace/ext/emmet", function() { + ace.require("ace/lib/net").loadScript("http://nightwing.github.io/emmet-core/emmet.js", function() { + embedded_editor.setOption("enableEmmet", true); + editor.setOption("enableEmmet", true); }); - - ace.config.loadModule("ace/ext/emmet", 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); - }); + + embedded_editor.setOptions({ + enableSnippets: true, + enableBasicAutocompletion: true }); - - ace.config.loadModule("ace/ext/language_tools", function() { - embedded_editor.setOptions({ - enableSnippets: true, - enableBasicAutocompletion: true - }); - editor.setOptions({ - enableSnippets: true, - enableBasicAutocompletion: true - }); - }); - } else { - document.body.insertAdjacentHTML("afterbegin", '
\ -
\ - \ - Oh No! Couldn\'t load build/src/ace.js.
\ - You can build it by running node Makefile.dryice.js
\ - Or download older version by running git submodule update --init --recursive
\ -
\ -
'); - } - $("ul.menu-list").mousedown(function(e) { - if (e.button === 1) { - e.preventDefault(); - } }); + ace.config.loadModule("ace/ext/language_tools", function() { + embedded_editor.setOptions({ + enableSnippets: true, + enableBasicAutocompletion: true + }); + editor.setOptions({ + enableSnippets: true, + enableBasicAutocompletion: true + }); + }); + + embedded_editor.setAutoScrollEditorIntoView(true); + editor.setAutoScrollEditorIntoView(true); + $("ul.menu-list li").click(function(e) { - if (e.target.tagName !== "A") { - var href = $(this).find("a").attr("href"); - if (e.button == 1) - window.open(href, "_blank"); - else - window.location = href; + if (e.target.tagName === "LI") { + console.log($(this).find("a")); + window.location = $(this).find("a").attr("href"); + } + else if (e.target.tagName === "P" || e.target.tagName === "IMG") { + var anchor = $(e.target).siblings(); + window.location = anchor.attr("href"); } }); @@ -147,22 +134,22 @@ $(function() { }); }); - $(window).on("hashchange", function(e) { - _gaq.push(['_trackPageview',location.pathname + location.search + location.hash]); - tabs.each(function() { + $(window).on("hashchange", function(e) { + _gaq.push(['_trackPageview',location.pathname + location.search + location.hash]); + tabs.each(function() { var idx = $.bbq.getState("nav") || "about"; var section = e.fragment.split("&")[1] || ""; $(this).find(tab_a_selector + "[href='#" + idx + "']").triggerHandler('click'); - + // handles dropping in from new link var api = $.bbq.getState("api"); if (api) { $(tab_a_selector + "[href='./api/" + api + ".html']").triggerHandler('click'); } - }); - }).trigger("hashchange"); + }); + }).trigger("hashchange"); - highlight(); + highlight(); }); @@ -171,17 +158,21 @@ function highlight() { var highlighter = ace.require("ace/ext/static_highlight") var dom = ace.require("ace/lib/dom") function qsa(sel) { - var els = document.querySelectorAll(sel); - var result = []; - for (var i = 0, l = els.length; i < l; i++) - result[i] = els[i]; - return result; + return [].slice.call(document.querySelectorAll(sel)); } qsa("code[class]").forEach(function(el) { var m = el.className.match(/language-(\w+)|(javascript)/); if (!m) return var mode = "ace/mode/" + (m[1] || m[2]); - highlighter.highlight(el, {mode: mode, theme: "ace/theme/xcode"}) + var theme = "ace/theme/xcode"; + var data = dom.getInnerText(el).trim(); + + highlighter.render(data, mode, theme, 1, true, function (highlighted) { + dom.importCssString(highlighted.css, "ace_highlight"); + el.innerHTML = highlighted.html; + }); }); + + } \ No newline at end of file diff --git a/doc/site/style.css b/doc/site/style.css index 1167340a..4e79b5fb 100644 --- a/doc/site/style.css +++ b/doc/site/style.css @@ -497,13 +497,11 @@ img { .rotating-logo { -webkit-transform: rotate(0deg); - transform: rotate(0deg); -webkit-transition: all 0.5s ease-out; transition: all 0.5s ease-out; } .rotating-logo:hover { -webkit-transform: rotate(360deg); - transform: rotate(360deg); -webkit-transition: all 0.5s ease-in-out; transition: all 0.5s ease-in-out; } \ No newline at end of file diff --git a/doc/wiki b/doc/wiki index d93670b4..a3d6d692 160000 --- a/doc/wiki +++ b/doc/wiki @@ -1 +1 @@ -Subproject commit d93670b47d776987b38bb2c31777c4e488338fac +Subproject commit a3d6d69286903155bc7e1e5cd9c0f541791d384b diff --git a/experiments/debug_mem_leak.html b/experiments/debug_mem_leak.html deleted file mode 100644 index b8ee8726..00000000 --- a/experiments/debug_mem_leak.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - -

- -
- - - \ No newline at end of file diff --git a/index.html b/index.html index e2440eb1..f2a26c2c 100644 --- a/index.html +++ b/index.html @@ -9,15 +9,12 @@ - - - + + - Fork me on GitHub + Fork me on GitHub
@@ -68,7 +65,7 @@ and is the successor of the Mozilla Skywriter (Bespin) project.

-
/**
+                                
/** * In fact, you're looking at ACE right now. Go ahead and play with it! * * We are currently showing off the JavaScript mode. ACE has support for 45 @@ -83,14 +80,14 @@ function add(x, y) { var addResult = add(3, 2); console.log(addResult); -
+

Looking for a more full-featured demo? Check out the kitchen sink.

Features

Now check out the How-To Guide for instructions on common operations, such as setting a different language mode or getting the contents from the editor.

-

Loading Ace from a Local URL

-

If you want to clone and host Ace locally you can +

Loading Ace from a Local URL

+

The above code is all you need to embed Ace in your site (including setting language modes + and themes). Plus it's super fast because it's on Amazon's distributed content network. +

+

But, if you want to clone host Ace locally you can use one of the pre-packaged versions. Just copy one of src* subdirectories somewhere into your project, or use RequireJS to load the - contents of lib/ace folder as ace: -

-

The packaged version can also be loaded from CDN's such as jsDelivr or cdnjs. + contents of lib/ace as ace:

+
var ace = require("lib/ace");

Working with Ace

@@ -196,7 +195,8 @@ console.log(addResult);

> See all themes

Setting the Programming Language Mode

By default, the editor supports plain text mode. All other language modes are available as separate modules, loaded on demand like this:

-
editor.getSession().setMode("ace/mode/javascript");
+
editor.getSession().setMode("ace/mode/javascript");
+                            
-
  • - - Repl.it -
  • -
  • - - Stypi -
  • Weecod
  • +
  • + + Live Workspace +
  • ProcessWire
  • +
  • + + Stypi +
  • +
  • + + Repl.it +
  • @@ -869,14 +880,14 @@ if (match) { Drive Notepad
  • - - Textor + + Fine Cut Engine
  • - PHP Assist + PHP Assist
  • @@ -887,10 +898,8 @@ if (match) { Evaluzio
  • -
    + CodeHelper
  • @@ -907,9 +916,9 @@ if (match) { BonsaiJS playground
  • - - Simply Text + + Acebug
  • @@ -939,20 +948,23 @@ if (match) { Debuggex
  • -
    S
    + -webkit-font-smoothing: antialiased; + font-size: 90px;text-align: center;line-height: 90px;">S
  • Slim Text
  • + Decor
  • - - Papeeria + + Divshot
  • - + + diff --git a/kitchen-sink.html b/kitchen-sink.html index a8e1fb7b..74f36a71 100644 --- a/kitchen-sink.html +++ b/kitchen-sink.html @@ -11,17 +11,23 @@ commit %commit% --> - - + + + + +
    - - + + -
    +
    @@ -57,7 +63,40 @@ @@ -253,13 +292,7 @@
    - - - - - +
    @@ -283,7 +316,7 @@ - + diff --git a/lib/ace/ace.js b/lib/ace/ace.js index 6c8a6126..34859be4 100644 --- a/lib/ace/ace.js +++ b/lib/ace/ace.js @@ -46,15 +46,14 @@ var Editor = require("./editor").Editor; var EditSession = require("./edit_session").EditSession; var UndoManager = require("./undomanager").UndoManager; var Renderer = require("./virtual_renderer").VirtualRenderer; +var MultiSelect = require("./multi_select").MultiSelect; // The following require()s are for inclusion in the built ace file require("./worker/worker_client"); require("./keyboard/hash_handler"); require("./placeholder"); -require("./multi_select"); require("./mode/folding/fold_mode"); require("./theme/textmate"); -require("./ext/error_marker"); exports.config = require("./config"); @@ -74,28 +73,19 @@ exports.require = require; exports.edit = function(el) { if (typeof(el) == "string") { var _id = el; - el = document.getElementById(_id); + var el = document.getElementById(_id); if (!el) - throw new Error("ace.edit can't find div #" + _id); + throw "ace.edit can't find div #" + _id; } - if (el && el.env && el.env.editor instanceof Editor) + if (el.env && el.env.editor instanceof Editor) return el.env.editor; - var value = ""; - if (el && /input|textarea/i.test(el.tagName)) { - var oldNode = el; - value = oldNode.value; - el = dom.createElement("pre"); - oldNode.parentNode.replaceChild(el, oldNode); - } else { - value = dom.getInnerText(el); - el.innerHTML = ''; - } - - var doc = exports.createEditSession(value); + var doc = exports.createEditSession(dom.getInnerText(el)); + el.innerHTML = ''; var editor = new Editor(new Renderer(el)); + new MultiSelect(editor); editor.setSession(doc); var env = { @@ -103,13 +93,11 @@ exports.edit = function(el) { editor: editor, onResize: editor.resize.bind(editor, null) }; - if (oldNode) env.textarea = oldNode; event.addListener(window, "resize", env.onResize); editor.on("destroy", function() { event.removeListener(window, "resize", env.onResize); - env.editor.container.env = null; // prevent memory leak on old ie }); - editor.container.env = editor.env = env; + el.env = editor.env = env; return editor; }; diff --git a/lib/ace/anchor.js b/lib/ace/anchor.js index 39b78e0f..3a62e632 100644 --- a/lib/ace/anchor.js +++ b/lib/ace/anchor.js @@ -36,7 +36,7 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter; /** * - * Defines a floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the anchor is updated. + * Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated. * * @class Anchor **/ @@ -99,54 +99,69 @@ var Anchor = exports.Anchor = function(doc, row, column) { * - `value`: An object describing the new Anchor position * **/ - this.onChange = function(delta) { - if (delta.start.row == delta.end.row && delta.start.row != this.row) + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) return; - if (delta.start.row > this.row) + if (range.start.row > this.row) return; - - var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); - this.setPosition(point.row, point.column, true); + + 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) { + 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); }; - - 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. @@ -176,14 +191,14 @@ var Anchor = exports.Anchor = function(doc, row, column) { this.row = pos.row; this.column = pos.column; - this._signal("change", { + this._emit("change", { old: old, value: pos }); }; /** - * When called, the `"change"` event listener is removed. + * When called, the `'change'` event listener is removed. * **/ this.detach = function() { diff --git a/lib/ace/anchor_test.js b/lib/ace/anchor_test.js index c0b97273..2d7fcb63 100644 --- a/lib/ace/anchor_test.js +++ b/lib/ace/anchor_test.js @@ -57,55 +57,20 @@ module.exports = { doc.insert({row: 1, column: 1}, "123"); assert.position(anchor.getPosition(), 1, 7); }, - - "test insert text at anchor should not move anchor when insertRight is true": function() { - var doc = new Document("juhu\nkinners"); - var anchor = new Anchor(doc, 1, 4); - anchor.$insertRight = true; - - doc.insert({row: 1, column: 4}, "123"); - assert.position(anchor.getPosition(), 1, 4); - }, "test insert lines before cursor should move anchor row": function() { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertFullLines(1, ["123", "456"]); + doc.insertLines(1, ["123", "456"]); assert.position(anchor.getPosition(), 3, 4); }, - - "test insert lines at anchor position should move anchor down": function() { - var doc = new Document("juhu\nkinners"); - var anchor = new Anchor(doc, 1, 0); - - doc.insertLines(1, ["line"]); - assert.position(anchor.getPosition(), 2, 0); - }, - - "test insert lines at anchor position should not move anchor down when insertRight is true and column is 0": function() { - var doc = new Document("juhu\nkinners"); - var anchor = new Anchor(doc, 1, 0); - anchor.$insertRight = true; - - doc.insertLines(1, ["line"]); - assert.position(anchor.getPosition(), 1, 0); - }, - - "test insert lines at anchor row should move anchor down when column > 0": function() { - var doc = new Document("juhu\nkinners"); - var anchor = new Anchor(doc, 1, 2); - anchor.$insertRight = true; - - doc.insertLines(1, ["line"]); - assert.position(anchor.getPosition(), 2, 2); - }, "test insert new line before cursor should move anchor column": function() { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertMergedLines({row: 0, column: 0}, ['', '']); + doc.insertNewLine({row: 0, column: 0}); assert.position(anchor.getPosition(), 2, 4); }, @@ -113,7 +78,7 @@ module.exports = { var doc = new Document("juhu\nkinners"); var anchor = new Anchor(doc, 1, 4); - doc.insertMergedLines({row: 1, column: 2}, ['', '']); + doc.insertNewLine({row: 1, column: 2}); assert.position(anchor.getPosition(), 2, 2); }, @@ -145,7 +110,7 @@ module.exports = { var doc = new Document("juhu\n1\n2\nkinners"); var anchor = new Anchor(doc, 3, 4); - doc.removeFullLines(1, 2); + doc.removeLines(1, 2); assert.position(anchor.getPosition(), 1, 4); }, @@ -169,7 +134,7 @@ module.exports = { var doc = new Document("juhu\nkinners\n123"); var anchor = new Anchor(doc, 1, 5); - doc.removeFullLines(1, 1); + doc.removeLines(1, 1); assert.position(anchor.getPosition(), 1, 0); }, @@ -208,9 +173,9 @@ module.exports = { var doc = new Document("juhu\nkinners\n123"); var anchor = new Anchor(doc, 2, 4); - doc.removeFullLines(0, 3); + doc.removeLines(0, 3); assert.position(anchor.getPosition(), 0, 0); - doc.insertFullLines(0, ["a", "b", "c"]); + doc.insertLines(0, ["a", "b", "c"]); assert.position(anchor.getPosition(), 3, 0); assert.equal(doc.getValue(), "a\nb\nc\n"); } diff --git a/lib/ace/apply_delta.js b/lib/ace/apply_delta.js deleted file mode 100644 index 98bfe148..00000000 --- a/lib/ace/apply_delta.js +++ /dev/null @@ -1,108 +0,0 @@ -/* ***** 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; - } -} -}); diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index 8e121f35..8f321800 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -36,14 +36,9 @@ var AcePopup = require("./autocomplete/popup").AcePopup; var util = require("./autocomplete/util"); var event = require("./lib/event"); var lang = require("./lib/lang"); -var dom = require("./lib/dom"); var snippetManager = require("./snippets").snippetManager; var Autocomplete = function() { - this.autoInsert = false; - this.autoSelect = true; - this.exactMatch = false; - this.gatherCompletionsId = 0; this.keyboardHandler = new HashHandler(); this.keyboardHandler.bindKeys(this.commands); @@ -51,31 +46,19 @@ var Autocomplete = function() { this.changeListener = this.changeListener.bind(this); this.mousedownListener = this.mousedownListener.bind(this); this.mousewheelListener = this.mousewheelListener.bind(this); - + this.changeTimer = lang.delayedCall(function() { this.updateCompletions(true); - }.bind(this)); - - this.tooltipTimer = lang.delayedCall(this.updateDocTooltip.bind(this), 50); + }.bind(this)) }; (function() { - this.$init = function() { this.popup = new AcePopup(document.body || document.documentElement); this.popup.on("click", function(e) { this.insertMatch(); e.stop(); }.bind(this)); - this.popup.focus = this.editor.focus.bind(this.editor); - this.popup.on("show", this.tooltipTimer.bind(null, null)); - this.popup.on("select", this.tooltipTimer.bind(null, null)); - this.popup.on("changeHoverMarker", this.tooltipTimer.bind(null, null)); - return this.popup; - }; - - this.getPopup = function() { - return this.popup || this.$init(); }; this.openPopup = function(editor, prefix, keepPopupPosition) { @@ -84,45 +67,36 @@ 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) { - this.popup.setTheme(editor.getTheme()); this.popup.setFontSize(editor.getFontSize()); var lineHeight = renderer.layerConfig.lineHeight; - - var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); + + var pos = renderer.$cursorLayer.getPixelPosition(this.base, true); pos.left -= this.popup.getTextLeftOffset(); - + var rect = editor.container.getBoundingClientRect(); pos.top += rect.top - renderer.layerConfig.offset; - pos.left += rect.left - editor.renderer.scrollLeft; - pos.left += renderer.gutterWidth; + pos.left += rect.left; + pos.left += renderer.$gutterLayer.gutterWidth; this.popup.show(pos, lineHeight); - } else if (keepPopupPosition && !prefix) { - this.detach(); } + renderer.updateText(); }; this.detach = function() { this.editor.keyBinding.removeKeyboardHandler(this.keyboardHandler); this.editor.off("changeSelection", this.changeListener); - this.editor.off("blur", this.blurListener); - this.editor.off("mousedown", this.mousedownListener); + this.editor.off("blur", this.changeListener); + this.editor.off("mousedown", this.changeListener); this.editor.off("mousewheel", this.mousewheelListener); this.changeTimer.cancel(); - this.hideDocTooltip(); - - this.gatherCompletionsId += 1; - if (this.popup && this.popup.isOpen) + + if (this.popup) this.popup.hide(); - if (this.base) - this.base.detach(); this.activated = false; this.completions = this.base = null; }; @@ -138,18 +112,9 @@ var Autocomplete = function() { this.detach(); }; - this.blurListener = function(e) { - // 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(); - 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.blurListener = function() { + if (document.activeElement != this.editor.textInput.getElement()) this.detach(); - } }; this.mousedownListener = function(e) { @@ -165,7 +130,7 @@ var Autocomplete = function() { var max = this.popup.session.getLength() - 1; switch(where) { - case "up": row = row <= 0 ? max : row - 1; break; + case "up": row = row < 0 ? max : row - 1; break; case "down": row = row >= max ? -1 : row + 1; break; case "start": row = 0; break; case "end": row = max; break; @@ -179,9 +144,8 @@ var Autocomplete = function() { data = this.popup.getData(this.popup.getRow()); if (!data) return false; - if (data.completer && data.completer.insertMatch) { - data.completer.insertMatch(this.editor, data); + data.completer.insertMatch(this.editor); } else { if (this.completions.filterText) { var ranges = this.editor.selection.getAllRanges(); @@ -198,7 +162,6 @@ var Autocomplete = function() { this.detach(); }; - this.commands = { "Up": function(editor) { editor.completer.goTo("up"); }, "Down": function(editor) { editor.completer.goTo("down"); }, @@ -206,15 +169,10 @@ var Autocomplete = function() { "Ctrl-Down|Ctrl-End": function(editor) { editor.completer.goTo("end"); }, "Esc": function(editor) { editor.completer.detach(); }, - "Return": function(editor) { return editor.completer.insertMatch(); }, + "Space": function(editor) { editor.completer.detach(); editor.insert(" ");}, + "Return": function(editor) { editor.completer.insertMatch(); }, "Shift-Return": function(editor) { editor.completer.insertMatch(true); }, - "Tab": function(editor) { - var result = editor.completer.insertMatch(); - if (!result && !editor.tabstopManager) - editor.completer.goTo("down"); - else - return result; - }, + "Tab": function(editor) { editor.completer.insertMatch(); }, "PageUp": function(editor) { editor.completer.popup.gotoPageUp(); }, "PageDown": function(editor) { editor.completer.popup.gotoPageDown(); } @@ -223,27 +181,24 @@ var Autocomplete = function() { this.gatherCompletions = function(editor, callback) { var session = editor.getSession(); var pos = editor.getCursorPosition(); - + var line = session.getLine(pos.row); var prefix = util.retrievePrecedingIdentifier(line, pos.column); - - this.base = session.doc.createAnchor(pos.row, pos.column - prefix.length); - this.base.$insertRight = true; + + this.base = editor.getCursorPosition(); + this.base.column -= prefix.length; var matches = []; - var total = editor.completers.length; - editor.completers.forEach(function(completer, i) { + util.parForEach(editor.completers, function(completer, next) { completer.getCompletions(editor, session, pos, prefix, function(err, results) { if (!err) matches = matches.concat(results); - // Fetch prefix again, because they may have changed by now - var pos = editor.getCursorPosition(); - var line = session.getLine(pos.row); - callback(null, { - prefix: util.retrievePrecedingIdentifier(line, pos.column, results[0] && results[0].identifierRegex), - matches: matches, - finished: (--total === 0) - }); + next(); + }); + }, function() { + callback(null, { + prefix: prefix, + matches: matches }); }); return true; @@ -252,7 +207,7 @@ var Autocomplete = function() { this.showPopup = function(editor) { if (this.editor) this.detach(); - + this.activated = true; this.editor = editor; @@ -262,14 +217,15 @@ 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); editor.on("mousewheel", this.mousewheelListener); - + this.updateCompletions(); - }; - + } + this.updateCompletions = function(keepPopupPosition) { if (keepPopupPosition && this.base && this.completions) { var pos = this.editor.getCursorPosition(); @@ -279,126 +235,33 @@ var Autocomplete = function() { this.completions.setFilter(prefix); if (!this.completions.filtered.length) return this.detach(); - if (this.completions.filtered.length == 1 - && this.completions.filtered[0].value == prefix - && !this.completions.filtered[0].snippet) - return this.detach(); this.openPopup(this.editor, prefix, keepPopupPosition); return; } - - // Save current gatherCompletions session, session is close when a match is insert - var _id = this.gatherCompletionsId; this.gatherCompletions(this.editor, function(err, results) { - // Only detach if result gathering is finished - var detachIfFinished = function() { - if (!results.finished) return; - return this.detach(); - }.bind(this); - - var prefix = results.prefix; var matches = results && results.matches; - if (!matches || !matches.length) - return detachIfFinished(); - - // Wrong prefix or wrong session -> ignore - if (prefix.indexOf(results.prefix) !== 0 || _id != this.gatherCompletionsId) - return; + return this.detach(); + // TODO reenable this when we have proper change tracking + // if (matches.length == 1) + // return this.insertMatch(matches[0]); this.completions = new FilteredList(matches); - - if (this.exactMatch) - this.completions.exactMatch = true; - - this.completions.setFilter(prefix); - var filtered = this.completions.filtered; - - // No results - if (!filtered.length) - return detachIfFinished(); - - // One result equals to the prefix - if (filtered.length == 1 && filtered[0].value == prefix && !filtered[0].snippet) - return detachIfFinished(); - - // Autoinsert if one result - if (this.autoInsert && filtered.length == 1 && results.finished) - return this.insertMatch(filtered[0]); - - this.openPopup(this.editor, prefix, keepPopupPosition); + this.completions.setFilter(results.prefix); + if (!this.completions.filtered.length) + return this.detach(); + this.openPopup(this.editor, results.prefix, keepPopupPosition); }.bind(this)); }; this.cancelContextMenu = function() { - this.editor.$mouseHandler.cancelContextMenu(); - }; - - this.updateDocTooltip = function() { - var popup = this.popup; - var all = popup.data; - var selected = all && (all[popup.getHoveredRow()] || all[popup.getRow()]); - var doc = null; - if (!selected || !this.editor || !this.popup.isOpen) - return this.hideDocTooltip(); - this.editor.completers.some(function(completer) { - if (completer.getDocTooltip) - doc = completer.getDocTooltip(selected); - return doc; - }); - if (!doc) - doc = selected; - - if (typeof doc == "string") - doc = {docText: doc}; - if (!doc || !(doc.docHTML || doc.docText)) - return this.hideDocTooltip(); - this.showDocTooltip(doc); - }; - - this.showDocTooltip = function(item) { - if (!this.tooltipNode) { - this.tooltipNode = dom.createElement("div"); - this.tooltipNode.className = "ace_tooltip ace_doc-tooltip"; - this.tooltipNode.style.margin = 0; - this.tooltipNode.style.pointerEvents = "auto"; - this.tooltipNode.tabIndex = -1; - this.tooltipNode.onblur = this.blurListener.bind(this); - } - - var tooltipNode = this.tooltipNode; - if (item.docHTML) { - tooltipNode.innerHTML = item.docHTML; - } else if (item.docText) { - tooltipNode.textContent = item.docText; - } - - if (!tooltipNode.parentNode) - document.body.appendChild(tooltipNode); - var popup = this.popup; - var rect = popup.container.getBoundingClientRect(); - tooltipNode.style.top = popup.container.style.top; - tooltipNode.style.bottom = popup.container.style.bottom; - - if (window.innerWidth - rect.right < 320) { - tooltipNode.style.right = window.innerWidth - rect.left + "px"; - tooltipNode.style.left = ""; - } else { - tooltipNode.style.left = (rect.right + 1) + "px"; - tooltipNode.style.right = ""; - } - tooltipNode.style.display = "block"; - }; - - this.hideDocTooltip = function() { - this.tooltipTimer.cancel(); - if (!this.tooltipNode) return; - var el = this.tooltipNode; - if (!this.editor.isFocused() && document.activeElement == el) - this.editor.focus(); - this.tooltipNode = null; - if (el.parentNode) - el.parentNode.removeChild(el); + var stop = function(e) { + this.editor.off("nativecontextmenu", stop); + if (e && e.domEvent) + event.stopEvent(e.domEvent); + }.bind(this); + setTimeout(stop, 10); + this.editor.on("nativecontextmenu", stop); }; }).call(Autocomplete.prototype); @@ -408,20 +271,17 @@ Autocomplete.startCommand = { exec: function(editor) { if (!editor.completer) editor.completer = new Autocomplete(); - editor.completer.autoInsert = false; - editor.completer.autoSelect = true; editor.completer.showPopup(editor); - // prevent ctrl-space opening context menu on firefox on mac + // needed for firefox on mac editor.completer.cancelContextMenu(); }, bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" }; -var FilteredList = function(array, filterText) { +var FilteredList = function(array, filterText, mutateData) { this.all = array; this.filtered = array; this.filterText = filterText || ""; - this.exactMatch = false; }; (function(){ this.setFilter = function(str) { @@ -435,16 +295,16 @@ var FilteredList = function(array, filterText) { matches = matches.sort(function(a, b) { return b.exactMatch - a.exactMatch || b.score - a.score; }); - + // make unique var prev = null; matches = matches.filter(function(item){ - var caption = item.snippet || item.caption || item.value; + var caption = item.value || item.caption || item.snippet; if (caption === prev) return false; prev = caption; return true; }); - + this.filtered = matches; }; this.filterCompletions = function(items, needle) { @@ -458,29 +318,23 @@ var FilteredList = function(array, filterText) { var matchMask = 0; var penalty = 0; var index, distance; - - if (this.exactMatch) { - if (needle !== caption.substr(0, needle.length)) + // caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf + for (var j = 0; j < needle.length; j++) { + // TODO add penalty on case mismatch + var i1 = caption.indexOf(lower[j], lastIndex + 1); + var i2 = caption.indexOf(upper[j], lastIndex + 1); + index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; + if (index < 0) continue loop; - }else{ - // caption char iteration is faster in Chrome but slower in Firefox, so lets use indexOf - for (var j = 0; j < needle.length; j++) { - // TODO add penalty on case mismatch - var i1 = caption.indexOf(lower[j], lastIndex + 1); - var i2 = caption.indexOf(upper[j], lastIndex + 1); - index = (i1 >= 0) ? ((i2 < 0 || i1 < i2) ? i1 : i2) : i2; - if (index < 0) - continue loop; - distance = index - lastIndex - 1; - if (distance > 0) { - // first char mismatch should be more sensitive - if (lastIndex === -1) - penalty += 10; - penalty += distance; - } - matchMask = matchMask | (1 << index); - lastIndex = index; + distance = index - lastIndex - 1; + if (distance > 0) { + // first char mismatch should be more sensitive + if (lastIndex === -1) + penalty += 10; + penalty += distance; } + matchMask = matchMask | (1 << index); + lastIndex = index; } item.matchMask = matchMask; item.exactMatch = penalty ? 0 : 1; diff --git a/lib/ace/autocomplete/popup.js b/lib/ace/autocomplete/popup.js index 6c480b38..4cf29073 100644 --- a/lib/ace/autocomplete/popup.js +++ b/lib/ace/autocomplete/popup.js @@ -31,6 +31,7 @@ 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; @@ -42,7 +43,7 @@ var $singleLineEditor = function(el) { var renderer = new Renderer(el); renderer.$maxLines = 4; - + var editor = new Editor(renderer); editor.setHighlightActiveLine(false); @@ -51,7 +52,6 @@ var $singleLineEditor = function(el) { editor.renderer.setHighlightGutterLine(false); editor.$mouseHandler.$focusWaitTimout = 0; - editor.$highlightTagPending = true; return editor; }; @@ -59,16 +59,13 @@ var $singleLineEditor = function(el) { var AcePopup = function(parentNode) { var el = dom.createElement("div"); var popup = new $singleLineEditor(el); - + if (parentNode) parentNode.appendChild(el); el.style.display = "none"; popup.renderer.content.style.cursor = "default"; popup.renderer.setStyle("ace_autocomplete"); - popup.setOption("displayIndentGuides", false); - popup.setOption("dragDelay", 150); - var noop = function(){}; popup.focus = noop; @@ -87,7 +84,8 @@ var AcePopup = function(parentNode) { popup.on("mousedown", function(e) { var pos = e.getDocumentPosition(); - popup.selection.moveToPosition(pos); + popup.moveCursorToPosition(pos); + popup.selection.clearSelection(); selectionMarker.start.row = selectionMarker.end.row = pos.row; e.stop(); }); @@ -103,23 +101,17 @@ var AcePopup = function(parentNode) { popup.session.removeMarker(hoverMarker.id); hoverMarker.id = null; } - }; - popup.setSelectOnHover(false); + } + popup.setSelectOnHover(false) popup.on("mousemove", function(e) { - if (!lastMouseEvent) { - lastMouseEvent = e; - return; - } - if (lastMouseEvent.x == e.x && lastMouseEvent.y == e.y) { - return; - } lastMouseEvent = e; lastMouseEvent.scrollTop = popup.renderer.scrollTop; var row = lastMouseEvent.getDocumentPosition().row; if (hoverMarker.start.row != row) { + popup.session._emit("changeBackMarker"); if (!hoverMarker.id) popup.setRow(row); - setHoverMarker(row); + hoverMarker.start.row = hoverMarker.end.row = row; } }); popup.renderer.on("beforeRender", function() { @@ -128,38 +120,17 @@ var AcePopup = function(parentNode) { var row = lastMouseEvent.getDocumentPosition().row; if (!hoverMarker.id) popup.setRow(row); - setHoverMarker(row, true); - } - }); - popup.renderer.on("afterRender", function() { - var row = popup.getRow(); - var t = popup.renderer.$textLayer; - var selected = t.element.childNodes[row - t.config.firstRow]; - if (selected == t.selectedNode) - return; - if (t.selectedNode) - dom.removeCssClass(t.selectedNode, "ace_selected"); - t.selectedNode = selected; - if (selected) - dom.addCssClass(selected, "ace_selected"); - }); - var hideHoverMarker = function() { setHoverMarker(-1) }; - var setHoverMarker = function(row, suppressRedraw) { - if (row !== hoverMarker.start.row) { hoverMarker.start.row = hoverMarker.end.row = row; - if (!suppressRedraw) - popup.session._emit("changeBackMarker"); - popup._emit("changeHoverMarker"); } + }); + var hideHoverMarker = function() { + hoverMarker.start.row = hoverMarker.end.row = -1; + popup.session._emit("changeBackMarker"); }; - popup.getHoveredRow = function() { - return hoverMarker.start.row; - }; - event.addListener(popup.container, "mouseout", hideHoverMarker); popup.on("hide", hideHoverMarker); popup.on("changeSelection", hideHoverMarker); - + popup.session.doc.getLength = function() { return popup.data.length; }; @@ -171,15 +142,15 @@ var AcePopup = function(parentNode) { }; var bgTokenizer = popup.session.bgTokenizer; - bgTokenizer.$tokenizeRow = function(row) { - var data = popup.data[row]; + bgTokenizer.$tokenizeRow = function(i) { + var data = popup.data[i]; var tokens = []; if (!data) return tokens; if (typeof data == "string") data = {value: data}; if (!data.caption) - data.caption = data.value || data.name; + data.caption = data.value; var last = -1; var flag, c; @@ -196,33 +167,22 @@ var AcePopup = function(parentNode) { if (data.meta) { var maxW = popup.renderer.$size.scrollerWidth / popup.renderer.layerConfig.characterWidth; - 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}); + if (data.meta.length + data.caption.length < maxW - 2) + tokens.push({type: "rightAlignedText", value: data.meta}); } return tokens; }; bgTokenizer.$updateOnChange = noop; - bgTokenizer.start = noop; - + popup.session.$computeWidth = function() { return this.screenWidth = 0; - }; - - popup.$blockScrolling = Infinity; + } // public - popup.isOpen = false; - popup.isTopdown = false; - popup.data = []; popup.setData = function(list) { - popup.setValue(lang.stringRepeat("\n", list.length), -1); popup.data = list || []; - popup.setRow(0); + popup.setValue(lang.stringRepeat("\n", list.length), -1); }; popup.getData = function(row) { return popup.data[row]; @@ -232,89 +192,57 @@ var AcePopup = function(parentNode) { return selectionMarker.start.row; }; popup.setRow = function(line) { - line = Math.max(-1, Math.min(this.data.length, line)); if (selectionMarker.start.row != line) { popup.selection.clearSelection(); selectionMarker.start.row = selectionMarker.end.row = line || 0; popup.session._emit("changeBackMarker"); popup.moveCursorTo(line || 0, 0); - if (popup.isOpen) - popup._signal("select"); } }; - popup.on("changeSelection", function() { - if (popup.isOpen) - popup.setRow(popup.selection.lead.row); - popup.renderer.scrollCursorIntoView(); - }); - popup.hide = function() { this.container.style.display = "none"; this._signal("hide"); - popup.isOpen = false; }; - popup.show = function(pos, lineHeight, topdownOnly) { + popup.show = function(pos, lineHeight) { var el = this.container; var screenHeight = window.innerHeight; - var screenWidth = window.innerWidth; var renderer = this.renderer; - // var maxLines = Math.min(renderer.$maxLines, this.session.getLength()); - var maxH = renderer.$maxLines * lineHeight * 1.4; - var top = pos.top + this.$borderSize; - if (top + maxH > screenHeight - lineHeight && !topdownOnly) { + var maxH = renderer.$maxLines * lineHeight; + if (pos.top +maxH > screenHeight - lineHeight) { el.style.top = ""; - el.style.bottom = screenHeight - top + "px"; - popup.isTopdown = false; + el.style.bottom = screenHeight - pos.top + "px"; } else { - top += lineHeight; - el.style.top = top + "px"; + pos.top += lineHeight; + el.style.top = pos.top + "px"; el.style.bottom = ""; - popup.isTopdown = true; } + el.style.left = pos.left + "px"; el.style.display = ""; this.renderer.$textLayer.checkForSizeChanges(); - var left = pos.left; - if (left + el.offsetWidth > screenWidth) - left = screenWidth - el.offsetWidth; - - el.style.left = left + "px"; - this._signal("show"); - lastMouseEvent = null; - popup.isOpen = true; }; - + popup.getTextLeftOffset = function() { - return this.$borderSize + this.renderer.$padding + this.$imageSize; - }; - - popup.$imageSize = 0; - popup.$borderSize = 1; + return 1 + this.renderer.layerConfig.padding; + } return popup; }; dom.importCssString("\ -.ace_editor.ace_autocomplete .ace_marker-layer .ace_active-line {\ +.ace_autocomplete.ace-tm .ace_marker-layer .ace_active-line {\ background-color: #CAD6FA;\ z-index: 1;\ }\ -.ace_editor.ace_autocomplete .ace_line-hover {\ +.ace_autocomplete.ace-tm .ace_line-hover {\ border: 1px solid #abbffe;\ - margin-top: -1px;\ - background: rgba(233,233,253,0.4);\ -}\ -.ace_editor.ace_autocomplete .ace_line-hover {\ position: absolute;\ + background: rgba(233,233,253,0.4);\ z-index: 2;\ -}\ -.ace_editor.ace_autocomplete .ace_scroller {\ - background: none;\ - border: none;\ - box-shadow: none;\ + margin-top: -1px;\ }\ .ace_rightAlignedText {\ color: gray;\ @@ -324,11 +252,11 @@ dom.importCssString("\ text-align: right;\ z-index: -1;\ }\ -.ace_editor.ace_autocomplete .ace_completion-highlight{\ +.ace_autocomplete .ace_completion-highlight{\ color: #000;\ text-shadow: 0 0 0.01em;\ }\ -.ace_editor.ace_autocomplete {\ +.ace_autocomplete {\ width: 280px;\ z-index: 200000;\ background: #fbfbfb;\ @@ -341,4 +269,4 @@ dom.importCssString("\ exports.AcePopup = AcePopup; -}); +}); \ No newline at end of file diff --git a/lib/ace/autocomplete/text_completer.js b/lib/ace/autocomplete/text_completer.js index 17a4bdad..87a25fb9 100644 --- a/lib/ace/autocomplete/text_completer.js +++ b/lib/ace/autocomplete/text_completer.js @@ -29,9 +29,9 @@ * ***** END LICENSE BLOCK ***** */ define(function(require, exports, module) { - var Range = require("../range").Range; + var Range = require("ace/range").Range; - var splitRegex = /[^a-zA-Z_0-9\$\-\u00C0-\u1FFF\u2C00-\uD7FF\w]+/; + var splitRegex = /[^a-zA-Z_0-9\$\-]+/; function getWordIndex(doc, pos) { var textBefore = doc.getTextRange(Range.fromPoints({row: 0, column:0}, pos)); @@ -68,11 +68,11 @@ define(function(require, exports, module) { var wordList = Object.keys(wordScore); callback(null, wordList.map(function(word) { return { - caption: word, + name: word, value: word, score: wordScore[word], meta: "local" }; })); }; -}); +}); \ No newline at end of file diff --git a/lib/ace/autocomplete/util.js b/lib/ace/autocomplete/util.js index 767b983e..8b7c1151 100644 --- a/lib/ace/autocomplete/util.js +++ b/lib/ace/autocomplete/util.js @@ -43,9 +43,9 @@ exports.parForEach = function(array, fn, callback) { callback(result, err); }); } -}; +} -var ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/; +var ID_REGEX = /[a-zA-Z_0-9\$-]/; exports.retrievePrecedingIdentifier = function(text, pos, regex) { regex = regex || ID_REGEX; @@ -57,7 +57,7 @@ exports.retrievePrecedingIdentifier = function(text, pos, regex) { break; } return buf.reverse().join(""); -}; +} exports.retrieveFollowingIdentifier = function(text, pos, regex) { regex = regex || ID_REGEX; @@ -69,6 +69,6 @@ exports.retrieveFollowingIdentifier = function(text, pos, regex) { break; } return buf; -}; +} }); diff --git a/lib/ace/background_tokenizer.js b/lib/ace/background_tokenizer.js index ea4ddd0f..1eb28794 100644 --- a/lib/ace/background_tokenizer.js +++ b/lib/ace/background_tokenizer.js @@ -36,6 +36,8 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter; /** + * + * * Tokenizes the current [[Document `Document`]] in the background, and caches the tokenized rows for future use. * * If a certain row is changed, everything below that row is re-tokenized. @@ -48,6 +50,8 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter; * @param {Tokenizer} tokenizer The tokenizer to use * @param {Editor} editor The editor to associate with * + * + * * @constructor **/ @@ -68,10 +72,11 @@ 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; @@ -84,9 +89,10 @@ var BackgroundTokenizer = function(tokenizer, editor) { // only check every 5 lines processedLines ++; - if ((processedLines % 5 === 0) && (new Date() - workerStart) > 20) { + if ((processedLines % 5 == 0) && (new Date() - workerStart) > 20) { self.running = setTimeout(self.$worker, 20); - break; + self.currentLine = currentLine; + return; } } self.currentLine = currentLine; @@ -144,7 +150,7 @@ var BackgroundTokenizer = function(tokenizer, editor) { first: firstRow, last: lastRow }; - this._signal("update", {data: data}); + this._emit("update", {data: data}); }; /** @@ -166,17 +172,17 @@ var BackgroundTokenizer = function(tokenizer, editor) { }; this.scheduleStart = function() { - if (!this.running) - this.running = setTimeout(this.$worker, 700); + this.running = setTimeout(this.$worker, 700); } this.$updateOnChange = function(delta) { - var startRow = delta.start.row; - var len = delta.end.row - startRow; + var range = delta.range; + var startRow = range.start.row; + var len = range.end.row - startRow; if (len === 0) { this.lines[startRow] = null; - } else if (delta.action == "remove") { + } else if (delta.action == "removeText" || delta.action == "removeLines") { this.lines.splice(startRow, len + 1, null); this.states.splice(startRow, len + 1, null); } else { diff --git a/lib/ace/background_tokenizer_test.js b/lib/ace/background_tokenizer_test.js index fd738d06..7a4cc78c 100644 --- a/lib/ace/background_tokenizer_test.js +++ b/lib/ace/background_tokenizer_test.js @@ -75,49 +75,6 @@ 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"]); } }; diff --git a/lib/ace/commands/command_manager.js b/lib/ace/commands/command_manager.js index df30ef9b..e8a581ad 100644 --- a/lib/ace/commands/command_manager.js +++ b/lib/ace/commands/command_manager.js @@ -2,44 +2,42 @@ define(function(require, exports, module) { "use strict"; var oop = require("../lib/oop"); -var MultiHashHandler = require("../keyboard/hash_handler").MultiHashHandler; +var HashHandler = require("../keyboard/hash_handler").HashHandler; var EventEmitter = require("../lib/event_emitter").EventEmitter; /** * @class CommandManager * + * **/ /** * new CommandManager(platform, commands) - * @param {String} platform Identifier for the platform; must be either `"mac"` or `"win"` + * @param {String} platform Identifier for the platform; must be either `'mac'` or `'win'` * @param {Array} commands A list of commands * **/ var CommandManager = function(platform, commands) { - MultiHashHandler.call(this, commands, platform); - this.byName = this.commands; + this.platform = platform; + this.commands = this.byName = {}; + this.commmandKeyBinding = {}; + + this.addCommands(commands); + this.setDefaultHandler("exec", function(e) { return e.command.exec(e.editor, e.args || {}); }); }; -oop.inherits(CommandManager, MultiHashHandler); +oop.inherits(CommandManager, HashHandler); (function() { oop.implement(this, EventEmitter); this.exec = function(command, editor, args) { - if (Array.isArray(command)) { - for (var i = command.length; i--; ) { - if (this.exec(command[i], editor, args)) return true; - } - return false; - } - - if (typeof command === "string") + if (typeof command === 'string') command = this.commands[command]; if (!command) @@ -49,10 +47,10 @@ oop.inherits(CommandManager, MultiHashHandler); return false; var e = {editor: editor, command: command, args: args}; - e.returnValue = this._emit("exec", e); + var retvalue = this._emit("exec", e); this._signal("afterExec", e); - return e.returnValue === false ? false : true; + return retvalue === false ? false : true; }; this.toggleRecording = function(editor) { diff --git a/lib/ace/commands/command_manager_test.js b/lib/ace/commands/command_manager_test.js index 902600be..76d973bb 100644 --- a/lib/ace/commands/command_manager_test.js +++ b/lib/ace/commands/command_manager_test.js @@ -188,7 +188,7 @@ module.exports = { assert.equal(command, "cm2"); var command = this.cm.findKeyCommand(0, "return"); - assert.equal(command + "", ["cm4", "cm3"] + ""); + assert.equal(command, "cm3"); } }; diff --git a/lib/ace/commands/default_commands.js b/lib/ace/commands/default_commands.js index de14df85..9c663d18 100644 --- a/lib/ace/commands/default_commands.js +++ b/lib/ace/commands/default_commands.js @@ -33,16 +33,14 @@ define(function(require, exports, module) { var lang = require("../lib/lang"); var config = require("../config"); -var Range = require("../range").Range; function bindKey(win, mac) { - return {win: win, mac: mac}; + return { + win: win, + mac: mac + }; } -/* - multiSelectAction: "forEach"|"forEachLine"|function|undefined, - scrollIntoView: true|"cursor"|"center"|"selectionPart" -*/ exports.commands = [{ name: "showSettingsMenu", bindKey: bindKey("Ctrl-,", "Command-,"), @@ -53,26 +51,6 @@ exports.commands = [{ }); }, readOnly: true -}, { - name: "goToNextError", - bindKey: bindKey("Alt-E", "Ctrl-E"), - exec: function(editor) { - config.loadModule("ace/ext/error_marker", function(module) { - module.showErrorMarker(editor, 1); - }); - }, - scrollIntoView: "animate", - readOnly: true -}, { - name: "goToPreviousError", - bindKey: bindKey("Alt-Shift-E", "Ctrl-Shift-E"), - exec: function(editor) { - config.loadModule("ace/ext/error_marker", function(module) { - module.showErrorMarker(editor, -1); - }); - }, - scrollIntoView: "animate", - readOnly: true }, { name: "selectall", bindKey: bindKey("Ctrl-A", "Command-A"), @@ -97,84 +75,31 @@ 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(null, "Ctrl-Command-Option-0"), - exec: function(editor) { editor.session.foldAll(); }, - scrollIntoView: "center", - readOnly: true -}, { - name: "foldOther", bindKey: bindKey("Alt-0", "Command-Option-0"), - exec: function(editor) { - editor.session.foldAll(); - editor.session.unfold(editor.selection.getAllRanges()); - }, - scrollIntoView: "center", + exec: function(editor) { editor.session.foldAll(); }, readOnly: true }, { name: "unfoldall", bindKey: bindKey("Alt-Shift-0", "Command-Option-Shift-0"), exec: function(editor) { editor.session.unfold(); }, - scrollIntoView: "center", readOnly: true }, { name: "findnext", bindKey: bindKey("Ctrl-K", "Command-G"), exec: function(editor) { editor.findNext(); }, - multiSelectAction: "forEach", - scrollIntoView: "center", readOnly: true }, { name: "findprevious", bindKey: bindKey("Ctrl-Shift-K", "Command-Shift-G"), exec: function(editor) { editor.findPrevious(); }, - multiSelectAction: "forEach", - scrollIntoView: "center", - readOnly: true -}, { - name: "selectOrFindNext", - bindKey: bindKey("Alt-K", "Ctrl-G"), - exec: function(editor) { - if (editor.selection.isEmpty()) - editor.selection.selectWord(); - else - editor.findNext(); - }, - readOnly: true -}, { - name: "selectOrFindPrevious", - bindKey: bindKey("Alt-Shift-K", "Ctrl-Shift-G"), - exec: function(editor) { - if (editor.selection.isEmpty()) - editor.selection.selectWord(); - else - editor.findPrevious(); - }, readOnly: true }, { name: "find", @@ -194,29 +119,25 @@ exports.commands = [{ exec: function(editor) { editor.getSelection().selectFileStart(); }, multiSelectAction: "forEach", readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" + group: "fileJump" }, { name: "gotostart", bindKey: bindKey("Ctrl-Home", "Command-Home|Command-Up"), exec: function(editor) { editor.navigateFileStart(); }, multiSelectAction: "forEach", readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" + group: "fileJump" }, { name: "selectup", bindKey: bindKey("Shift-Up", "Shift-Up"), exec: function(editor) { editor.getSelection().selectUp(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "golineup", bindKey: bindKey("Up", "Up|Ctrl-P"), exec: function(editor, args) { editor.navigateUp(args.times); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selecttoend", @@ -224,113 +145,97 @@ exports.commands = [{ exec: function(editor) { editor.getSelection().selectFileEnd(); }, multiSelectAction: "forEach", readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" + group: "fileJump" }, { name: "gotoend", bindKey: bindKey("Ctrl-End", "Command-End|Command-Down"), exec: function(editor) { editor.navigateFileEnd(); }, multiSelectAction: "forEach", readOnly: true, - scrollIntoView: "animate", - aceCommandGroup: "fileJump" + group: "fileJump" }, { name: "selectdown", bindKey: bindKey("Shift-Down", "Shift-Down"), exec: function(editor) { editor.getSelection().selectDown(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "golinedown", bindKey: bindKey("Down", "Down|Ctrl-N"), exec: function(editor, args) { editor.navigateDown(args.times); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selectwordleft", bindKey: bindKey("Ctrl-Shift-Left", "Option-Shift-Left"), exec: function(editor) { editor.getSelection().selectWordLeft(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "gotowordleft", bindKey: bindKey("Ctrl-Left", "Option-Left"), exec: function(editor) { editor.navigateWordLeft(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selecttolinestart", bindKey: bindKey("Alt-Shift-Left", "Command-Shift-Left"), exec: function(editor) { editor.getSelection().selectLineStart(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "gotolinestart", bindKey: bindKey("Alt-Left|Home", "Command-Left|Home|Ctrl-A"), exec: function(editor) { editor.navigateLineStart(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selectleft", bindKey: bindKey("Shift-Left", "Shift-Left"), exec: function(editor) { editor.getSelection().selectLeft(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "gotoleft", bindKey: bindKey("Left", "Left|Ctrl-B"), exec: function(editor, args) { editor.navigateLeft(args.times); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selectwordright", bindKey: bindKey("Ctrl-Shift-Right", "Option-Shift-Right"), exec: function(editor) { editor.getSelection().selectWordRight(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "gotowordright", bindKey: bindKey("Ctrl-Right", "Option-Right"), exec: function(editor) { editor.navigateWordRight(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selecttolineend", bindKey: bindKey("Alt-Shift-Right", "Command-Shift-Right"), exec: function(editor) { editor.getSelection().selectLineEnd(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "gotolineend", bindKey: bindKey("Alt-Right|End", "Command-Right|End|Ctrl-E"), exec: function(editor) { editor.navigateLineEnd(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selectright", bindKey: bindKey("Shift-Right", "Shift-Right"), exec: function(editor) { editor.getSelection().selectRight(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "gotoright", bindKey: bindKey("Right", "Right|Ctrl-F"), exec: function(editor, args) { editor.navigateRight(args.times); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selectpagedown", @@ -377,14 +282,12 @@ exports.commands = [{ bindKey: "Shift-Home", exec: function(editor) { editor.getSelection().selectLineStart(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "selectlineend", bindKey: "Shift-End", exec: function(editor) { editor.getSelection().selectLineEnd(); }, multiSelectAction: "forEach", - scrollIntoView: "cursor", readOnly: true }, { name: "togglerecording", @@ -398,38 +301,17 @@ exports.commands = [{ readOnly: true }, { name: "jumptomatching", - bindKey: bindKey("Ctrl-P", "Ctrl-P"), + bindKey: bindKey("Ctrl-P", "Ctrl-Shift-P"), exec: function(editor) { editor.jumpToMatching(); }, multiSelectAction: "forEach", - scrollIntoView: "animate", readOnly: true }, { name: "selecttomatching", - bindKey: bindKey("Ctrl-Shift-P", "Ctrl-Shift-P"), + bindKey: bindKey("Ctrl-Shift-P", null), exec: function(editor) { editor.jumpToMatching(true); }, multiSelectAction: "forEach", - scrollIntoView: "animate", readOnly: true -}, { - name: "expandToMatching", - bindKey: bindKey("Ctrl-Shift-M", "Ctrl-Shift-M"), - exec: function(editor) { editor.jumpToMatching(true, true); }, - multiSelectAction: "forEach", - scrollIntoView: "animate", - readOnly: true -}, { - name: "passKeysToBrowser", - 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 { @@ -443,55 +325,41 @@ exports.commands = [{ editor.clearSelection(); } }, - scrollIntoView: "cursor", multiSelectAction: "forEach" -}, { - name: "paste", - exec: function(editor, args) { - editor.$handlePaste(args); - }, - scrollIntoView: "cursor" }, { name: "removeline", bindKey: bindKey("Ctrl-D", "Command-D"), exec: function(editor) { editor.removeLines(); }, - scrollIntoView: "cursor", multiSelectAction: "forEachLine" }, { name: "duplicateSelection", bindKey: bindKey("Ctrl-Shift-D", "Command-Shift-D"), exec: function(editor) { editor.duplicateSelection(); }, - scrollIntoView: "cursor", multiSelectAction: "forEach" }, { name: "sortlines", bindKey: bindKey("Ctrl-Alt-S", "Command-Alt-S"), exec: function(editor) { editor.sortLines(); }, - scrollIntoView: "selection", multiSelectAction: "forEachLine" }, { name: "togglecomment", bindKey: bindKey("Ctrl-/", "Command-/"), exec: function(editor) { editor.toggleCommentLines(); }, - multiSelectAction: "forEachLine", - scrollIntoView: "selectionPart" + multiSelectAction: "forEachLine" }, { name: "toggleBlockComment", bindKey: bindKey("Ctrl-Shift-/", "Command-Shift-/"), exec: function(editor) { editor.toggleBlockComment(); }, - multiSelectAction: "forEach", - scrollIntoView: "selectionPart" + multiSelectAction: "forEach" }, { name: "modifyNumberUp", bindKey: bindKey("Ctrl-Shift-Up", "Alt-Shift-Up"), exec: function(editor) { editor.modifyNumber(1); }, - scrollIntoView: "cursor", multiSelectAction: "forEach" }, { name: "modifyNumberDown", bindKey: bindKey("Ctrl-Shift-Down", "Alt-Shift-Down"), exec: function(editor) { editor.modifyNumber(-1); }, - scrollIntoView: "cursor", multiSelectAction: "forEach" }, { name: "replace", @@ -510,29 +378,24 @@ exports.commands = [{ }, { name: "copylinesup", bindKey: bindKey("Alt-Shift-Up", "Command-Option-Up"), - exec: function(editor) { editor.copyLinesUp(); }, - scrollIntoView: "cursor" + exec: function(editor) { editor.copyLinesUp(); } }, { name: "movelinesup", bindKey: bindKey("Alt-Up", "Option-Up"), - exec: function(editor) { editor.moveLinesUp(); }, - scrollIntoView: "cursor" + exec: function(editor) { editor.moveLinesUp(); } }, { name: "copylinesdown", bindKey: bindKey("Alt-Shift-Down", "Command-Option-Down"), - exec: function(editor) { editor.copyLinesDown(); }, - scrollIntoView: "cursor" + exec: function(editor) { editor.copyLinesDown(); } }, { name: "movelinesdown", bindKey: bindKey("Alt-Down", "Option-Down"), - exec: function(editor) { editor.moveLinesDown(); }, - scrollIntoView: "cursor" + exec: function(editor) { editor.moveLinesDown(); } }, { name: "del", bindKey: bindKey("Delete", "Delete|Ctrl-D|Shift-Delete"), exec: function(editor) { editor.remove("right"); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "backspace", bindKey: bindKey( @@ -540,8 +403,7 @@ exports.commands = [{ "Ctrl-Backspace|Shift-Backspace|Backspace|Ctrl-H" ), exec: function(editor) { editor.remove("left"); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "cut_or_delete", bindKey: bindKey("Shift-Delete", null), @@ -552,186 +414,77 @@ exports.commands = [{ return false; } }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "removetolinestart", bindKey: bindKey("Alt-Backspace", "Command-Backspace"), exec: function(editor) { editor.removeToLineStart(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "removetolineend", bindKey: bindKey("Alt-Delete", "Ctrl-K"), exec: function(editor) { editor.removeToLineEnd(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "removewordleft", bindKey: bindKey("Ctrl-Backspace", "Alt-Backspace|Ctrl-Alt-Backspace"), exec: function(editor) { editor.removeWordLeft(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "removewordright", bindKey: bindKey("Ctrl-Delete", "Alt-Delete"), exec: function(editor) { editor.removeWordRight(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "outdent", bindKey: bindKey("Shift-Tab", "Shift-Tab"), exec: function(editor) { editor.blockOutdent(); }, - multiSelectAction: "forEach", - scrollIntoView: "selectionPart" + multiSelectAction: "forEach" }, { name: "indent", bindKey: bindKey("Tab", "Tab"), exec: function(editor) { editor.indent(); }, - multiSelectAction: "forEach", - scrollIntoView: "selectionPart" -}, { + multiSelectAction: "forEach" +},{ name: "blockoutdent", bindKey: bindKey("Ctrl-[", "Ctrl-["), exec: function(editor) { editor.blockOutdent(); }, - multiSelectAction: "forEachLine", - scrollIntoView: "selectionPart" -}, { + multiSelectAction: "forEachLine" +},{ name: "blockindent", bindKey: bindKey("Ctrl-]", "Ctrl-]"), exec: function(editor) { editor.blockIndent(); }, - multiSelectAction: "forEachLine", - scrollIntoView: "selectionPart" + multiSelectAction: "forEachLine" }, { name: "insertstring", exec: function(editor, str) { editor.insert(str); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "inserttext", exec: function(editor, args) { editor.insert(lang.stringRepeat(args.text || "", args.times || 1)); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "splitline", bindKey: bindKey(null, "Ctrl-O"), exec: function(editor) { editor.splitLine(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "transposeletters", bindKey: bindKey("Ctrl-T", "Ctrl-T"), exec: function(editor) { editor.transposeLetters(); }, - multiSelectAction: function(editor) {editor.transposeSelections(1); }, - scrollIntoView: "cursor" + multiSelectAction: function(editor) {editor.transposeSelections(1); } }, { name: "touppercase", bindKey: bindKey("Ctrl-U", "Ctrl-U"), exec: function(editor) { editor.toUpperCase(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" + multiSelectAction: "forEach" }, { name: "tolowercase", bindKey: bindKey("Ctrl-Shift-U", "Ctrl-Shift-U"), exec: function(editor) { editor.toLowerCase(); }, - multiSelectAction: "forEach", - scrollIntoView: "cursor" -}, { - name: "expandtoline", - bindKey: bindKey("Ctrl-Shift-L", "Command-Shift-L"), - exec: function(editor) { - var range = editor.selection.getRange(); - - range.start.column = range.end.column = 0; - range.end.row++; - editor.selection.setRange(range, false); - }, - multiSelectAction: "forEach", - scrollIntoView: "cursor", - readOnly: true -}, { - name: "joinlines", - bindKey: bindKey(null, null), - exec: function(editor) { - var isBackwards = editor.selection.isBackwards(); - var selectionStart = isBackwards ? editor.selection.getSelectionLead() : editor.selection.getSelectionAnchor(); - var selectionEnd = isBackwards ? editor.selection.getSelectionAnchor() : editor.selection.getSelectionLead(); - var firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length; - var selectedText = editor.session.doc.getTextRange(editor.selection.getRange()); - var selectedCount = selectedText.replace(/\n\s*/, " ").length; - var insertLine = editor.session.doc.getLine(selectionStart.row); - - for (var i = selectionStart.row + 1; i <= selectionEnd.row + 1; i++) { - var curLine = lang.stringTrimLeft(lang.stringTrimRight(editor.session.doc.getLine(i))); - if (curLine.length !== 0) { - curLine = " " + curLine; - } - insertLine += curLine; - } - - if (selectionEnd.row + 1 < (editor.session.doc.getLength() - 1)) { - // Don't insert a newline at the end of the document - insertLine += editor.session.doc.getNewLineCharacter(); - } - - editor.clearSelection(); - editor.session.doc.replace(new Range(selectionStart.row, 0, selectionEnd.row + 2, 0), insertLine); - - if (selectedCount > 0) { - // Select the text that was previously selected - editor.selection.moveCursorTo(selectionStart.row, selectionStart.column); - editor.selection.selectTo(selectionStart.row, selectionStart.column + selectedCount); - } else { - // If the joined line had something in it, start the cursor at that something - firstLineEndCol = editor.session.doc.getLine(selectionStart.row).length > firstLineEndCol ? (firstLineEndCol + 1) : firstLineEndCol; - editor.selection.moveCursorTo(selectionStart.row, firstLineEndCol); - } - }, - multiSelectAction: "forEach", - readOnly: true -}, { - name: "invertSelection", - bindKey: bindKey(null, null), - exec: function(editor) { - var endRow = editor.session.doc.getLength() - 1; - var endCol = editor.session.doc.getLine(endRow).length; - var ranges = editor.selection.rangeList.ranges; - var newRanges = []; - - // If multiple selections don't exist, rangeList will return 0 so replace with single range - if (ranges.length < 1) { - ranges = [editor.selection.getRange()]; - } - - for (var i = 0; i < ranges.length; i++) { - if (i == (ranges.length - 1)) { - // The last selection must connect to the end of the document, unless it already does - if (!(ranges[i].end.row === endRow && ranges[i].end.column === endCol)) { - newRanges.push(new Range(ranges[i].end.row, ranges[i].end.column, endRow, endCol)); - } - } - - if (i === 0) { - // The first selection must connect to the start of the document, unless it already does - if (!(ranges[i].start.row === 0 && ranges[i].start.column === 0)) { - newRanges.push(new Range(0, 0, ranges[i].start.row, ranges[i].start.column)); - } - } else { - newRanges.push(new Range(ranges[i-1].end.row, ranges[i-1].end.column, ranges[i].start.row, ranges[i].start.column)); - } - } - - editor.exitMultiSelectMode(); - editor.clearSelection(); - - for(var i = 0; i < newRanges.length; i++) { - editor.selection.addRange(newRanges[i], false); - } - }, - readOnly: true, - scrollIntoView: "none" + multiSelectAction: "forEach" }]; }); diff --git a/lib/ace/commands/incremental_search_commands.js b/lib/ace/commands/incremental_search_commands.js index 59083a85..ebe979ca 100644 --- a/lib/ace/commands/incremental_search_commands.js +++ b/lib/ace/commands/incremental_search_commands.js @@ -69,14 +69,18 @@ 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"}, @@ -84,30 +88,42 @@ exports.iSearchCommands = [{ options.useCurrentOrPrevSearch = true; options.backwards = true; iSearch.next(options); - } + }, + readOnly: true, + isIncrementalSearchCommand: true }, { name: "extendSearchTerm", exec: function(iSearch, string) { - iSearch.addString(string); - } + iSearch.addChar(string); + }, + readOnly: true, + isIncrementalSearchCommand: true }, { name: "extendSearchTermSpace", bindKey: "space", - exec: function(iSearch) { iSearch.addString(' '); } + exec: function(iSearch) { iSearch.addChar(' '); }, + readOnly: true, + isIncrementalSearchCommand: true }, { name: "shrinkSearchTerm", bindKey: "backspace", exec: function(iSearch) { iSearch.removeChar(); - } + }, + readOnly: true, + isIncrementalSearchCommand: true }, { name: 'confirmSearch', bindKey: 'return', - exec: function(iSearch) { iSearch.deactivate(); } + exec: function(iSearch) { iSearch.deactivate(); }, + readOnly: true, + isIncrementalSearchCommand: true }, { name: 'cancelSearch', bindKey: 'esc|Ctrl-G', - exec: function(iSearch) { iSearch.deactivate(true); } + exec: function(iSearch) { iSearch.deactivate(true); }, + readOnly: true, + isIncrementalSearchCommand: true }, { name: 'occurisearch', bindKey: 'Ctrl-O', @@ -115,53 +131,10 @@ exports.iSearchCommands = [{ var options = oop.mixin({}, iSearch.$options); iSearch.deactivate(); occurStartCommand.exec(iSearch.$editor, options); - } -}, { - name: "yankNextWord", - bindKey: "Ctrl-w", - exec: function(iSearch) { - var ed = iSearch.$editor, - range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorWordRight(); }), - string = ed.session.getTextRange(range); - iSearch.addString(string); - } -}, { - name: "yankNextChar", - bindKey: "Ctrl-Alt-y", - exec: function(iSearch) { - var ed = iSearch.$editor, - range = ed.selection.getRangeOfMovements(function(sel) { sel.moveCursorRight(); }), - string = ed.session.getTextRange(range); - iSearch.addString(string); - } -}, { - name: 'recenterTopBottom', - bindKey: 'Ctrl-l', - exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); } -}, { - name: 'selectAllMatches', - bindKey: 'Ctrl-space', - exec: function(iSearch) { - var ed = iSearch.$editor, - hl = ed.session.$isearchHighlight, - ranges = hl && hl.cache ? hl.cache - .reduce(function(ranges, ea) { - return ranges.concat(ea ? ea : []); }, []) : []; - iSearch.deactivate(false); - ranges.forEach(ed.selection.addRange.bind(ed.selection)); - } -}, { - name: 'searchAsRegExp', - bindKey: 'Alt-r', - exec: function(iSearch) { - iSearch.convertNeedleToRegExp(); - } -}].map(function(cmd) { - cmd.readOnly = true; - cmd.isIncrementalSearchCommand = true; - cmd.scrollIntoView = "animate-cursor"; - return cmd; -}); + }, + readOnly: true, + isIncrementalSearchCommand: true +}]; function IncrementalSearchKeyboardHandler(iSearch) { this.$iSearch = iSearch; @@ -169,7 +142,7 @@ function IncrementalSearchKeyboardHandler(iSearch) { oop.inherits(IncrementalSearchKeyboardHandler, HashHandler); -(function() { +;(function() { this.attach = function(editor) { var iSearch = this.$iSearch; @@ -178,24 +151,18 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler); if (!e.command.isIncrementalSearchCommand) return undefined; e.stopPropagation(); e.preventDefault(); - 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; + return e.command.exec(iSearch, e.args || {}); }); - }; + } 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) { - if (((hashId === 1/*ctrl*/ || hashId === 8/*command*/) && key === 'v') - || (hashId === 1/*ctrl*/ && key === 'y')) return null; var cmd = handleKeyboard$super.call(this, data, hashId, key, keyCode); if (cmd.command) { return cmd; } if (hashId == -1) { @@ -203,7 +170,7 @@ oop.inherits(IncrementalSearchKeyboardHandler, HashHandler); if (extendCmd) { return {command: extendCmd, args: key}; } } return {command: "null", passEvent: hashId == 0 || hashId == 4}; - }; + } }).call(IncrementalSearchKeyboardHandler.prototype); diff --git a/lib/ace/commands/multi_select_commands.js b/lib/ace/commands/multi_select_commands.js index ba6392bc..ff59f045 100644 --- a/lib/ace/commands/multi_select_commands.js +++ b/lib/ace/commands/multi_select_commands.js @@ -35,49 +35,41 @@ exports.defaultCommands = [{ name: "addCursorAbove", exec: function(editor) { editor.selectMoreLines(-1); }, bindKey: {win: "Ctrl-Alt-Up", mac: "Ctrl-Alt-Up"}, - scrollIntoView: "cursor", readonly: true }, { name: "addCursorBelow", exec: function(editor) { editor.selectMoreLines(1); }, bindKey: {win: "Ctrl-Alt-Down", mac: "Ctrl-Alt-Down"}, - scrollIntoView: "cursor", readonly: true }, { name: "addCursorAboveSkipCurrent", exec: function(editor) { editor.selectMoreLines(-1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Up", mac: "Ctrl-Alt-Shift-Up"}, - scrollIntoView: "cursor", readonly: true }, { name: "addCursorBelowSkipCurrent", exec: function(editor) { editor.selectMoreLines(1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Down", mac: "Ctrl-Alt-Shift-Down"}, - scrollIntoView: "cursor", readonly: true }, { name: "selectMoreBefore", exec: function(editor) { editor.selectMore(-1); }, bindKey: {win: "Ctrl-Alt-Left", mac: "Ctrl-Alt-Left"}, - scrollIntoView: "cursor", readonly: true }, { name: "selectMoreAfter", exec: function(editor) { editor.selectMore(1); }, bindKey: {win: "Ctrl-Alt-Right", mac: "Ctrl-Alt-Right"}, - scrollIntoView: "cursor", readonly: true }, { name: "selectNextBefore", exec: function(editor) { editor.selectMore(-1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Left", mac: "Ctrl-Alt-Shift-Left"}, - scrollIntoView: "cursor", readonly: true }, { name: "selectNextAfter", exec: function(editor) { editor.selectMore(1, true); }, bindKey: {win: "Ctrl-Alt-Shift-Right", mac: "Ctrl-Alt-Shift-Right"}, - scrollIntoView: "cursor", readonly: true }, { name: "splitIntoLines", @@ -87,14 +79,7 @@ exports.defaultCommands = [{ }, { name: "alignCursors", exec: function(editor) { editor.alignCursors(); }, - bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"}, - scrollIntoView: "cursor" -}, { - name: "findAll", - exec: function(editor) { editor.findAll(); }, - bindKey: {win: "Ctrl-Alt-K", mac: "Ctrl-Alt-G"}, - scrollIntoView: "cursor", - readonly: true + bindKey: {win: "Ctrl-Alt-A", mac: "Ctrl-Alt-A"} }]; // commands active only in multiselect mode @@ -102,7 +87,6 @@ exports.multiSelectCommands = [{ name: "singleSelection", bindKey: "esc", exec: function(editor) { editor.exitMultiSelectMode(); }, - scrollIntoView: "cursor", readonly: true, isAvailable: function(editor) {return editor && editor.inMultiSelectMode} }]; diff --git a/lib/ace/config.js b/lib/ace/config.js index fe9312fd..eb3de049 100644 --- a/lib/ace/config.js +++ b/lib/ace/config.js @@ -34,12 +34,10 @@ define(function(require, exports, module) { var lang = require("./lib/lang"); var oop = require("./lib/oop"); var net = require("./lib/net"); -var AppConfig = require("./lib/app_config").AppConfig; - -module.exports = exports = new AppConfig(); +var EventEmitter = require("./lib/event_emitter").EventEmitter; var global = (function() { - return this || typeof window != "undefined" && window; + return this; })(); var options = { @@ -71,6 +69,8 @@ exports.all = function() { }; // module loading +oop.implement(exports, EventEmitter); + exports.moduleUrl = function(name, component) { if (options.$moduleUrls[name]) return options.$moduleUrls[name]; @@ -80,9 +80,9 @@ exports.moduleUrl = function(name, component) { // todo make this configurable or get rid of '-' var sep = component == "snippets" ? "/" : "-"; - var base = parts[parts.length - 1]; - if (component == "worker" && sep == "-") { - var re = new RegExp("^" + component + "[\\-_]|[\\-_]" + component + "$", "g"); + var base = parts[parts.length - 1]; + if (sep == "-") { + var re = new RegExp("^" + component + "[\-_]|[\-_]" + component + "$", "g"); base = base.replace(re, ""); } @@ -113,7 +113,7 @@ exports.loadModule = function(moduleName, onLoad) { try { module = require(moduleName); - } catch (e) {} + } catch (e) {}; // require(moduleName) can return empty object if called after require([moduleName], callback) if (module && !exports.$loading[moduleName]) return onLoad && onLoad(module); @@ -142,9 +142,10 @@ exports.loadModule = function(moduleName, onLoad) { net.loadScript(exports.moduleUrl(moduleName, moduleType), afterLoad); }; + // initialization -function init(packaged) { - options.packaged = packaged || require.packaged || module.packaged || (global.define && define.packaged); +exports.init = function() { + options.packaged = require.packaged || module.packaged || (global.define && define.packaged); if (!global.document) return ""; @@ -152,11 +153,7 @@ function init(packaged) { var scriptOptions = {}; var scriptUrl = ""; - // Use currentScript.ownerDocument in case this file was loaded from imported document. (HTML Imports) - var currentScript = (document.currentScript || document._currentScript ); // native or polyfill - var currentDocument = currentScript && currentScript.ownerDocument || document; - - var scripts = currentDocument.getElementsByTagName("script"); + var scripts = document.getElementsByTagName("script"); for (var i=0; i .ace_gutter-cell { @@ -324,7 +323,7 @@ width: 11px; vertical-align: top; - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg=="); + background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82"); background-repeat: no-repeat; background-position: center; @@ -339,22 +338,26 @@ } .ace_fold-widget.ace_end { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42m3HwQkAMAhD0YzsRchFKI7sAikeWkrxwScEB0nh5e7KTPWimZki4tYfVbX+MNl4pyZXejUO1QAAAABJRU5ErkJggg=="); + background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82"); } .ace_fold-widget.ace_closed { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAGCAYAAAAG5SQMAAAAOUlEQVR42jXKwQkAMAgDwKwqKD4EwQ26sSOkVWjgIIHAzPiCgaqiqnJHZnKICBERHN194O5b9vbLuAVRL+l0YWnZAAAAAElFTkSuQmCCXA=="); + background-image: url("data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82"); } .ace_fold-widget:hover { border: 1px solid rgba(0, 0, 0, 0.3); background-color: rgba(255, 255, 255, 0.2); + -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); + -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7); } .ace_fold-widget:active { border: 1px solid rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.05); + -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); + -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); } /** @@ -374,6 +377,8 @@ background-color: rgba(255, 255, 255, 0.1); } .ace_dark .ace_fold-widget:active { + -moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); + -webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2); } @@ -383,13 +388,19 @@ } .ace_fade-fold-widgets .ace_fold-widget { + -moz-transition: opacity 0.4s ease 0.05s; -webkit-transition: opacity 0.4s ease 0.05s; + -o-transition: opacity 0.4s ease 0.05s; + -ms-transition: opacity 0.4s ease 0.05s; transition: opacity 0.4s ease 0.05s; opacity: 0; } .ace_fade-fold-widgets:hover .ace_fold-widget { + -moz-transition: opacity 0.05s ease 0.05s; -webkit-transition: opacity 0.05s ease 0.05s; + -o-transition: opacity 0.05s ease 0.05s; + -ms-transition: opacity 0.05s ease 0.05s; transition: opacity 0.05s ease 0.05s; opacity:1; } @@ -422,30 +433,3 @@ 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<= 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; }; /** @@ -261,160 +241,158 @@ var Document = function(textOrLines) { * **/ this.insert = function(position, text) { - // Only detect new lines if the document has no line break yet. + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + + // only detect new lines if the document has no line break yet if (this.getLength() <= 1) this.$detectNewLine(text); - - return this.insertMergedLines(position, this.$split(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 position; }; - + /** - * 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. - * + * 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. + * + **/ + /** + * Inserts the elements in `lines` into the document, 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: + * ``` + * {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.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 + if (lines.length > 0xFFFF) { + var end = this._insertLines(row, lines.slice(0xFFFF)); + lines = lines.slice(0, 0xFFFF); + } + + 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, + lines: lines + }; + this._emit("change", { data: delta }); + return end || 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:
    + * ``` + * {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._emit("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) { - 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; - }; + if (text.length == 0) + 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: - * - * * `"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 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: - * ``` - * {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.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 line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); - /** - * 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 + row : position.row, + column : position.column + text.length }; - - this.applyDelta({ - start: start, - end: end, - action: "insert", - lines: lines - }); - - return this.clonePos(end); + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._emit("change", { data: delta }); + + return end; }; /** @@ -424,90 +402,113 @@ var Document = function(textOrLines) { * **/ this.remove = function(range) { - 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); + 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; }; /** - * 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.
    If `startColumn` is equal to `endColumn`, this function returns nothing. - * - **/ + * 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.
    If `startColumn` is equal to `endColumn`, this function returns nothing. + * + **/ this.removeInLine = function(row, startColumn, endColumn) { - 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); + 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._emit("change", { data: delta }); + return range.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.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; + 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._emit("change", { data: delta }); + return removed; }; /** - * 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) { - 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: ["", ""] - }); - } + 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._emit("change", { data: delta }); }; /** @@ -523,7 +524,7 @@ var Document = function(textOrLines) { this.replace = function(range, text) { 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 @@ -532,106 +533,55 @@ var Document = function(textOrLines) { return range.end; this.remove(range); - var end; if (text) { - end = this.insert(range.start, text); + var end = this.insert(range.start, text); } else { end = range.start; } - + return end; }; /** - * Applies all changes in `deltas` to the document. - * @param {Array} deltas An array of delta objects (can include "insert" and "remove" actions) + * Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`. **/ this.applyDeltas = function(deltas) { for (var i=0; i=0; i--) { - this.revertDelta(deltas[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); } }; - - /** - * 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. * diff --git a/lib/ace/document_test.js b/lib/ace/document_test.js index ada56cd2..5c324db0 100644 --- a/lib/ace/document_test.js +++ b/lib/ace/document_test.js @@ -46,7 +46,7 @@ module.exports = { var doc = new Document(["12", "34"]); var deltas = []; - doc.on("change", function(e) { deltas.push(e); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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); }); + doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertMergedLines({row: 0, column: 1}, ['', '']); + doc.insertNewLine({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); }); + doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertFullLines(0, ["aa", "bb"]); + doc.insertLines(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); }); + doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertFullLines(2, ["aa", "bb"]); + doc.insertLines(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); }); + doc.on("change", function(e) { deltas.push(e.data); }); - doc.insertFullLines(1, ["aa", "bb"]); + doc.insertLines(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); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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); }); + doc.on("change", function(e) { deltas.push(e.data); }); - doc.insert({row: 1, column: 2}, "aa\nbb\ncc"); + doc.insert({row: 2, column: 0}, "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); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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); }); + doc.on("change", function(e) { deltas.push(e.data); }); 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.removeFullLines(1, 2); + var removed = doc.removeLines(1, 2); assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n")); }, @@ -296,35 +296,6 @@ 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"); - } } }; diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 2aa9b378..98c1e940 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -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); @@ -163,7 +163,7 @@ var EditSession = function(text, mode) { config.resetOptions(this); this.setMode(mode); - config._signal("session", this); + config._emit("session", this); }; @@ -249,12 +249,13 @@ var EditSession = function(text, mode) { this.$resetRowCache(fold.start.row); }; - this.onChange = function(delta) { + this.onChange = function(e) { + var delta = e.data; this.$modified = true; - this.$resetRowCache(delta.start.row); + this.$resetRowCache(delta.range.start.row); - var removedFolds = this.$updateInternalDataOnChange(delta); + var removedFolds = this.$updateInternalDataOnChange(e); if (!this.$fromUndo && this.$undoManager && !delta.ignore) { this.$deltasDoc.push(delta); if (removedFolds && removedFolds.length != 0) { @@ -267,24 +268,26 @@ var EditSession = function(text, mode) { this.$informUndoManager.schedule(); } - this.bgTokenizer && this.bgTokenizer.$updateOnChange(delta); - this._signal("change", delta); + this.bgTokenizer.$updateOnChange(delta); + this._emit("change", e); }; /** * Sets the session text. * @param {String} text The new text to place * + * + * **/ this.setValue = function(text) { this.doc.setValue(text); - this.selection.moveTo(0, 0); + this.selection.moveCursorTo(0, 0); + this.selection.clearSelection(); this.$resetRowCache(0); this.$deltas = []; this.$deltasDoc = []; this.$deltasFold = []; - this.setUndoManager(this.$undoManager); this.getUndoManager().reset(); }; @@ -409,7 +412,7 @@ var EditSession = function(text, mode) { } self.mergeUndoDeltas = false; self.$deltas = []; - }; + } this.$informUndoManager = lang.delayedCall(this.$syncInformUndoManager); } }; @@ -467,7 +470,7 @@ var EditSession = function(text, mode) { * @param {Number} tabSize The new tab size **/ this.setTabSize = function(tabSize) { - this.setOption("tabSize", tabSize); + this.setOption("tabSize", tabSize) }; /** * Returns the current tab size. @@ -483,7 +486,7 @@ var EditSession = function(text, mode) { * **/ this.isTabStop = function(position) { - return this.$useSoftTabs && (position.column % this.$tabSize === 0); + return this.$useSoftTabs && (position.column % this.$tabSize == 0); }; this.$overwrite = false; @@ -497,7 +500,7 @@ var EditSession = function(text, mode) { * **/ this.setOverwrite = function(overwrite) { - this.setOption("overwrite", overwrite); + this.setOption("overwrite", overwrite) }; /** @@ -525,7 +528,7 @@ var EditSession = function(text, mode) { if (!this.$decorations[row]) this.$decorations[row] = ""; this.$decorations[row] += " " + className; - this._signal("changeBreakpoint", {}); + this._emit("changeBreakpoint", {}); }; /** @@ -537,7 +540,7 @@ var EditSession = function(text, mode) { **/ this.removeGutterDecoration = function(row, className) { this.$decorations[row] = (this.$decorations[row] || "").replace(" " + className, ""); - this._signal("changeBreakpoint", {}); + this._emit("changeBreakpoint", {}); }; /** @@ -560,7 +563,7 @@ var EditSession = function(text, mode) { for (var i=0; i width) - width = w.screenWidth; - }); - return this.lineWidgetWidth = width; - }; this.$computeWidth = function(force) { if (this.$modified || force) { @@ -1145,19 +1139,6 @@ 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. @@ -1234,36 +1215,39 @@ var EditSession = function(text, mode) { this.$getUndoSelection = function(deltas, isUndo, lastUndoRange) { function isInsert(delta) { - return isUndo ? delta.action !== "insert" : delta.action === "insert"; + var insert = + delta.action === "insertText" || delta.action === "insertLines"; + return isUndo ? !insert : insert; } var delta = deltas[0]; var range, point; var lastDeltaIsInsert = false; if (isInsert(delta)) { - range = Range.fromPoints(delta.start, delta.end); + range = Range.fromPoints(delta.range.start, delta.range.end); lastDeltaIsInsert = true; } else { - range = Range.fromPoints(delta.start, delta.start); + range = Range.fromPoints(delta.range.start, delta.range.start); lastDeltaIsInsert = false; } for (var i = 1; i < deltas.length; i++) { delta = deltas[i]; if (isInsert(delta)) { - point = delta.start; + point = delta.range.start; if (range.compare(point.row, point.column) == -1) { - range.setStart(point); + range.setStart(delta.range.start); } - point = delta.end; + point = delta.range.end; if (range.compare(point.row, point.column) == 1) { - range.setEnd(point); + range.setEnd(delta.range.end); } lastDeltaIsInsert = true; } else { - point = delta.start; + point = delta.range.start; if (range.compare(point.row, point.column) == -1) { - range = Range.fromPoints(delta.start, delta.start); + range = + Range.fromPoints(delta.range.start, delta.range.start); } lastDeltaIsInsert = false; } @@ -1272,7 +1256,7 @@ var EditSession = function(text, mode) { // Check if this range and the last undo range has something in common. // If true, merge the ranges. if (lastUndoRange != null) { - if (Range.comparePoints(lastUndoRange.start, range.start) === 0) { + if (Range.comparePoints(lastUndoRange.start, range.start) == 0) { lastUndoRange.start.column += range.end.column - range.start.column; lastUndoRange.end.column += range.end.column - range.start.column; } @@ -1377,7 +1361,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.doc.insertInLine({row: row, column: 0}, indentString); + this.insert({row: row, column:0}, indentString); }; /** @@ -1434,11 +1418,11 @@ var EditSession = function(text, mode) { x.end.row += diff; return x; }); - + var lines = dir == 0 ? this.doc.getLines(firstRow, lastRow) - : this.doc.removeFullLines(firstRow, lastRow); - this.doc.insertFullLines(firstRow+diff, lines); + : this.doc.removeLines(firstRow, lastRow); + this.doc.insertLines(firstRow+diff, lines); folds.length && this.addFolds(folds); return diff; }; @@ -1448,6 +1432,8 @@ 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); @@ -1458,6 +1444,8 @@ 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); @@ -1556,11 +1544,14 @@ var EditSession = function(text, mode) { // If wrapMode is activaed, the wrapData array has to be initialized. if (useWrapMode) { var len = this.getLength(); - this.$wrapData = Array(len); + this.$wrapData = []; + for (var i = 0; i < len; i++) { + this.$wrapData.push([]); + } this.$updateWrapData(0, len - 1); } - this._signal("changeWrapMode"); + this._emit("changeWrapMode"); } }; @@ -1585,11 +1576,13 @@ 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 - if (this.$useWrapMode) - this._signal("changeWrapMode"); + this._emit("changeWrapMode"); } }; @@ -1601,7 +1594,7 @@ var EditSession = function(text, mode) { * @private **/ this.adjustWrapLimit = function(desiredLimit, $printMargin) { - var limits = this.$wrapLimitRange; + var limits = this.$wrapLimitRange if (limits.max < 0) limits = {min: $printMargin, max: $printMargin}; var wrapLimit = this.$constrainWrapLimit(desiredLimit, limits.min, limits.max); @@ -1611,7 +1604,7 @@ var EditSession = function(text, mode) { if (this.$useWrapMode) { this.$updateWrapData(0, this.getLength() - 1); this.$resetRowCache(0); - this._signal("changeWrapLimit"); + this._emit("changeWrapLimit"); } return true; } @@ -1661,23 +1654,34 @@ var EditSession = function(text, mode) { }; }; - this.$updateInternalDataOnChange = function(delta) { + this.$updateInternalDataOnChange = function(e) { var useWrapMode = this.$useWrapMode; - 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 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 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 === "remove") { + if (action.indexOf("remove") != -1) { this[useWrapMode ? "$wrapData" : "$rowLengthCache"].splice(firstRow, len); var foldLines = this.$foldData; - removedFolds = this.getFoldsInRange(delta); + removedFolds = this.getFoldsInRange(e.data.range); this.removeFolds(removedFolds); var foldLine = this.getFoldLine(end.row); @@ -1703,10 +1707,16 @@ var EditSession = function(text, mode) { lastRow = firstRow; } else { - var args = Array(len); - args.unshift(firstRow, 0); - var arr = useWrapMode ? this.$wrapData : this.$rowLengthCache - arr.splice.apply(arr, args); + var args; + if (useWrapMode) { + args = [firstRow, 0]; + for (var i = 0; i < len; i++) args.push([]); + this.$wrapData.splice.apply(this.$wrapData, args); + } else { + args = Array(len); + args.unshift(firstRow, 0); + this.$rowLengthCache.splice.apply(this.$rowLengthCache, args); + } // If some new line is added inside of a foldLine, then split // the fold line up. @@ -1714,14 +1724,13 @@ var EditSession = function(text, mode) { var foldLine = this.getFoldLine(firstRow); var idx = 0; if (foldLine) { - var cmp = foldLine.range.compareInside(start.row, start.column); + var cmp = foldLine.range.compareInside(start.row, start.column) // Inside of the foldLine range. Need to split stuff up. if (cmp == 0) { foldLine = foldLine.split(start.row, start.column); - if (foldLine) { - foldLine.shiftRow(len); - foldLine.addRemoveChars(lastRow, 0, end.column - start.column); - } + foldLine.shiftRow(len); + foldLine.addRemoveChars( + lastRow, 0, end.column - start.column); } else // Infront of the foldLine but same row. Need to shift column. if (cmp == -1) { @@ -1742,10 +1751,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(delta.start.column - delta.end.column); - if (action === "remove") { + len = Math.abs(e.data.range.start.column - e.data.range.end.column); + if (action.indexOf("remove") != -1) { // Get all the folds in the change range and remove them. - removedFolds = this.getFoldsInRange(delta); + removedFolds = this.getFoldsInRange(e.data.range); this.removeFolds(removedFolds); len = -len; @@ -1812,7 +1821,8 @@ var EditSession = function(text, mode) { lines[foldLine.end.row].length + 1 ); - wrapData[foldLine.start.row] = this.$computeWrapSplits(tokens, wrapLimit, tabSize); + wrapData[foldLine.start.row] + = this.$computeWrapSplits(tokens, wrapLimit, tabSize); row = foldLine.end.row + 1; } } @@ -1829,7 +1839,7 @@ var EditSession = function(text, mode) { TAB_SPACE = 12; - this.$computeWrapSplits = function(tokens, wrapLimit, tabSize) { + this.$computeWrapSplits = function(tokens, wrapLimit) { if (tokens.length == 0) { return []; } @@ -1840,31 +1850,6 @@ 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); @@ -1881,18 +1866,14 @@ var EditSession = function(text, mode) { len -= 1; }); - if (!splits.length) { - indent = getWrapIndent(); - splits.indent = indent; - } lastDocSplit += len; splits.push(lastDocSplit); lastSplit = screenPos; } - var indent = 0; - while (displayLength - lastSplit > wrapLimit - indent) { + + while (displayLength - lastSplit > wrapLimit) { // This is, where the split should be. - var split = lastSplit + wrapLimit - indent; + var split = lastSplit + wrapLimit; // If there is a space or tab at this split position, then making // a split is simple. @@ -1952,7 +1933,7 @@ var EditSession = function(text, mode) { // === ELSE === // Search for the first non space/tab/placeholder/punctuation token backwards. - var minSplit = Math.max(split - (wrapLimit -(wrapLimit>>2)), lastSplit - 1); + var minSplit = Math.max(split - (isCode ? 10 : wrapLimit-(wrapLimit>>2)), lastSplit - 1); while (split > minSplit && tokens[split] < PLACEHOLDER_START) { split --; } @@ -1978,9 +1959,7 @@ var EditSession = function(text, mode) { split = lastSplit + wrapLimit; // The split is inside of a CHAR or CHAR_EXT token and no space // around -> force a split. - if (tokens[split] == CHAR_EXT) - split--; - addSplit(split - indent); + addSplit(split); } return splits; }; @@ -2032,6 +2011,9 @@ var EditSession = function(text, mode) { * The first position indicates the number of columns for `str` on screen.
    * The second value contains the position of the document column that this function read until. * + * + * + * **/ this.$getStringScreenWidth = function(str, maxScreenColumn, screenColumn) { if (maxScreenColumn == 0) @@ -2061,7 +2043,6 @@ var EditSession = function(text, mode) { return [screenColumn, column]; }; - this.lineWidgets = null; /** * Returns number of screenrows in a wrapped line. * @param {Number} row The row number to check @@ -2069,17 +2050,6 @@ var EditSession = function(text, mode) { * @returns {Number} **/ this.getRowLength = function(row) { - if (this.lineWidgets) - var h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; - else - h = 0 - if (!this.$useWrapMode || !this.$wrapData[row]) { - return 1 + h; - } else { - return this.$wrapData[row].length + 1 + h; - } - }; - this.getRowLineCount = function(row) { if (!this.$useWrapMode || !this.$wrapData[row]) { return 1; } else { @@ -2087,16 +2057,6 @@ 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,7 +2163,7 @@ var EditSession = function(text, mode) { while (row <= screenRow) { rowLength = this.getRowLength(docRow); - if (row + rowLength > screenRow || docRow >= maxRow) { + if (row + rowLength - 1 >= screenRow || docRow >= maxRow) { break; } else { row += rowLength; @@ -2229,26 +2189,24 @@ var EditSession = function(text, mode) { return { row: maxRow, column: this.getLine(maxRow).length - }; + } } else { 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]; + column = splits[screenRow - row]; + if(screenRow > row && splits.length) { + docColumn = splits[screenRow - row - 1] || splits[splits.length - 1]; line = line.substring(docColumn); } } } - docColumn += this.$getStringScreenWidth(line, screenColumn - wrapIndent)[1]; + docColumn += this.$getStringScreenWidth(line, screenColumn)[1]; // We remove one character at the end so that the docColumn // position returned is not associated to the next row on the screen. @@ -2340,26 +2298,22 @@ 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]; - if (wrapRow) { - var screenRowOffset = 0; - while (textLine.length >= wrapRow[screenRowOffset]) { - screenRow ++; - screenRowOffset++; - } - textLine = textLine.substring( - wrapRow[screenRowOffset - 1] || 0, textLine.length - ); - wrapIndent = screenRowOffset > 0 ? wrapRow.indent : 0; + var screenRowOffset = 0; + while (textLine.length >= wrapRow[screenRowOffset]) { + screenRow ++; + screenRowOffset++; } + textLine = textLine.substring( + wrapRow[screenRowOffset - 1] || 0, textLine.length + ); } return { row: screenRow, - column: wrapIndent + this.$getStringScreenWidth(textLine)[0] + column: this.$getStringScreenWidth(textLine)[0] }; }; @@ -2408,8 +2362,7 @@ var EditSession = function(text, mode) { var foldStart = fold ? fold.start.row :Infinity; while (row < lastRow) { - var splits = this.$wrapData[row]; - screenRows += splits ? splits.length + 1 : 1; + screenRows += this.$wrapData[row].length + 1; row ++; if (row > foldStart) { row = fold.end.row+1; @@ -2419,31 +2372,16 @@ var EditSession = function(text, mode) { } } - // todo - if (this.lineWidgets) - screenRows += this.$getWidgetScreenLength(); - return screenRows; }; - - /** - * @private - * - */ - this.$setFontMetrics = function(fm) { - // todo - }; - - this.destroy = function() { - if (this.bgTokenizer) { - this.bgTokenizer.setDocument(null); - this.bgTokenizer = null; - } - this.$stopWorker(); - }; // For every keystroke this gets called once per char in the whole doc!! // Wouldn't hurt to make it a bit faster for c >= 0x1100 + + /** + * @private + * + */ function isFullWidth(c) { if (c < 0x1100) return false; @@ -2501,7 +2439,6 @@ config.defineOptions(EditSession.prototype, "session", { if (this.$wrap == value) return; - this.$wrap = value; if (!value) { this.setUseWrapMode(false); } else { @@ -2509,39 +2446,25 @@ config.defineOptions(EditSession.prototype, "session", { this.setWrapLimitRange(col, col); this.setUseWrapMode(true); } + this.$wrap = value; }, get: function() { - if (this.getUseWrapMode()) { - if (this.$wrap == -1) - return "printMargin"; - if (!this.getWrapLimitRange().min) - return "free"; - return this.$wrap; - } - return "off"; + return this.getUseWrapMode() ? this.getWrapLimitRange().min || "free" : "off"; }, handlesSet: true }, wrapMethod: { // code|text|auto set: function(val) { - val = val == "auto" - ? this.$mode.type != "text" - : val != "text"; - if (val != this.$wrapAsCode) { - this.$wrapAsCode = val; - if (this.$useWrapMode) { - this.$modified = true; - this.$resetRowCache(0); - this.$updateWrapData(0, this.getLength() - 1); - } - } + if (val == "auto") + this.$wrapAsCode = this.$mode.type != "text"; + else + this.$wrapAsCode = val != "text"; }, initialValue: "auto" }, - indentedSoftWrap: { initialValue: true }, firstLineNumber: { - set: function() {this._signal("changeBreakpoint");}, + set: function() {this._emit("changeBreakpoint");}, initialValue: 1 }, useWorker: { @@ -2562,23 +2485,19 @@ config.defineOptions(EditSession.prototype, "session", { this.$modified = true; this.$rowLengthCache = []; this.$tabSize = tabSize; - this._signal("changeTabSize"); + this._emit("changeTabSize"); }, initialValue: 4, handlesSet: true }, overwrite: { - set: function(val) {this._signal("changeOverwrite");}, + set: function(val) {this._emit("changeOverwrite");}, initialValue: false }, newLineMode: { set: function(val) {this.doc.setNewLineMode(val)}, get: function() {return this.doc.getNewLineMode()}, handlesSet: true - }, - mode: { - set: function(val) { this.setMode(val) }, - get: function() { return this.$modeId } } }); diff --git a/lib/ace/edit_session/bracket_match.js b/lib/ace/edit_session/bracket_match.js index 62a8499c..c3de2465 100644 --- a/lib/ace/edit_session/bracket_match.js +++ b/lib/ace/edit_session/bracket_match.js @@ -102,7 +102,7 @@ function BracketMatch() { "}": "{" }; - this.$findOpeningBracket = function(bracket, position, typeRe) { + this.$findOpeningBracket = function(bracket, position, type) { var openBracket = this.$brackets[bracket]; var depth = 1; @@ -113,21 +113,14 @@ function BracketMatch() { if (!token) return; - if (!typeRe){ - typeRe = new RegExp( - "(\\.?" + - token.type.replace(".", "\\.").replace("rparen", ".paren") - .replace(/\b(?:end)\b/, "(?:start|begin|end)") - + ")+" - ); - } + if (!type) + type = token.type.replace(/\.(?:rparen|lparen|start|end)$/, ""); // Start searching in token, just before the character at position.column var valueIndex = position.column - iterator.getCurrentTokenColumn() - 2; var value = token.value; - while (true) { - + while (true) { while (valueIndex >= 0) { var chr = value.charAt(valueIndex); if (chr == openBracket) { @@ -147,7 +140,7 @@ function BracketMatch() { // whose type matches typeRe do { token = iterator.stepBackward(); - } while (token && !typeRe.test(token.type)); + } while (token && token.type.lastIndexOf(type, 0)); if (token == null) break; @@ -156,10 +149,10 @@ function BracketMatch() { valueIndex = value.length - 1; } - return null; + return false; }; - this.$findClosingBracket = function(bracket, position, typeRe) { + this.$findClosingBracket = function(bracket, position, type) { var closingBracket = this.$brackets[bracket]; var depth = 1; @@ -170,20 +163,13 @@ function BracketMatch() { if (!token) return; - if (!typeRe){ - typeRe = new RegExp( - "(\\.?" + - token.type.replace(".", "\\.").replace("lparen", ".paren") - .replace(/\b(?:start|begin)\b/, "(?:start|begin|end)") - + ")+" - ); - } + if (!type) + type = token.type.replace(/\.(?:rparen|lparen|start|end)$/, ""); // Start searching in token, after the character at position.column var valueIndex = position.column - iterator.getCurrentTokenColumn(); while (true) { - var value = token.value; var valueLength = value.length; while (valueIndex < valueLength) { @@ -205,7 +191,7 @@ function BracketMatch() { // whose type matches typeRe do { token = iterator.stepForward(); - } while (token && !typeRe.test(token.type)); + } while (token && token.type.lastIndexOf(type, 0)); if (token == null) break; @@ -213,7 +199,7 @@ function BracketMatch() { valueIndex = 0; } - return null; + return false; }; } exports.BracketMatch = BracketMatch; diff --git a/lib/ace/edit_session/fold.js b/lib/ace/edit_session/fold.js index 232101bd..0f898021 100644 --- a/lib/ace/edit_session/fold.js +++ b/lib/ace/edit_session/fold.js @@ -78,7 +78,7 @@ oop.inherits(Fold, RangeList); return; if (!this.range.containsRange(fold)) - throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + throw "A fold can't intersect already existing fold" + fold.range + this.range; // transform fold to local coordinates consumeRange(fold, this.start); @@ -104,7 +104,7 @@ oop.inherits(Fold, RangeList); var afterEnd = this.subFolds[j]; if (cmp == 0) - throw new Error("A fold can't intersect already existing fold" + fold.range + this.range); + throw "A fold can't intersect already existing fold" + fold.range + this.range; var consumedFolds = this.subFolds.splice(i, j - i, fold); fold.setFoldLine(this.foldLine); diff --git a/lib/ace/edit_session/fold_line.js b/lib/ace/edit_session/fold_line.js index 9d73154d..e9f732c4 100644 --- a/lib/ace/edit_session/fold_line.js +++ b/lib/ace/edit_session/fold_line.js @@ -44,7 +44,7 @@ function FoldLine(foldData, folds) { folds = this.folds = [ folds ]; } - var last = folds[folds.length - 1]; + var last = folds[folds.length - 1] this.range = new Range(folds[0].start.row, folds[0].start.column, last.end.row, last.end.column); this.start = this.range.start; @@ -66,12 +66,12 @@ function FoldLine(foldData, folds) { fold.start.row += shift; fold.end.row += shift; }); - }; + } this.addFold = function(fold) { if (fold.sameRow) { if (fold.start.row < this.startRow || fold.endRow > this.endRow) { - throw new Error("Can't add a fold to this FoldLine as it has no connection"); + throw "Can't add a fold to this FoldLine as it has no connection"; } this.folds.push(fold); this.folds.sort(function(a, b) { @@ -93,20 +93,20 @@ function FoldLine(foldData, folds) { this.start.row = fold.start.row; this.start.column = fold.start.column; } else { - throw new Error("Trying to add fold to FoldRow that doesn't have a matching row"); + throw "Trying to add fold to FoldRow that doesn't have a matching row"; } fold.foldLine = this; - }; + } this.containsRow = function(row) { return row >= this.start.row && row <= this.end.row; - }; + } this.walk = function(callback, endRow, endColumn) { var lastEnd = 0, folds = this.folds, fold, - cmp, stop, isNewRow = true; + comp, stop, isNewRow = true; if (endRow == null) { endRow = this.end.row; @@ -116,9 +116,9 @@ function FoldLine(foldData, folds) { for (var i = 0; i < folds.length; i++) { fold = folds[i]; - cmp = fold.range.compareStart(endRow, endColumn); + comp = fold.range.compareStart(endRow, endColumn); // This fold is after the endRow/Column. - if (cmp == -1) { + if (comp == -1) { callback(null, endRow, endColumn, lastEnd, isNewRow); return; } @@ -127,8 +127,8 @@ function FoldLine(foldData, folds) { stop = !stop && callback(fold.placeholder, fold.start.row, fold.start.column, lastEnd); // If the user requested to stop the walk or endRow/endColumn is - // inside of this fold (cmp == 0), then end here. - if (stop || cmp === 0) { + // inside of this fold (comp == 0), then end here. + if (stop || comp == 0) { return; } @@ -138,7 +138,7 @@ function FoldLine(foldData, folds) { lastEnd = fold.end.column; } callback(null, endRow, endColumn, lastEnd, isNewRow); - }; + } this.getNextFoldTo = function(row, column) { var fold, cmp; @@ -150,15 +150,15 @@ function FoldLine(foldData, folds) { fold: fold, kind: "after" }; - } else if (cmp === 0) { + } else if (cmp == 0) { return { fold: fold, kind: "inside" - }; + } } } return null; - }; + } this.addRemoveChars = function(row, column, len) { var ret = this.getNextFoldTo(row, column), @@ -175,7 +175,7 @@ function FoldLine(foldData, folds) { } else if (fold.start.row == row) { folds = this.folds; var i = folds.indexOf(fold); - if (i === 0) { + if (i == 0) { this.start.column += len; } for (i; i < folds.length; i++) { @@ -189,18 +189,16 @@ function FoldLine(foldData, folds) { this.end.column += len; } } - }; + } this.split = function(row, column) { - var pos = this.getNextFoldTo(row, column); - - if (!pos || pos.kind == "inside") - return null; - - var fold = pos.fold; + var fold = this.getNextFoldTo(row, column).fold; var folds = this.folds; var foldData = this.foldData; - + + if (!fold) + return null; + var i = folds.indexOf(fold); var foldBefore = folds[i - 1]; this.end.row = foldBefore.end.row; @@ -213,7 +211,7 @@ function FoldLine(foldData, folds) { var newFoldLine = new FoldLine(foldData, folds); foldData.splice(foldData.indexOf(this) + 1, 0, newFoldLine); return newFoldLine; - }; + } this.merge = function(foldLineNext) { var folds = foldLineNext.folds; @@ -224,7 +222,7 @@ function FoldLine(foldData, folds) { // it's merged now with foldLineNext. var foldData = this.foldData; foldData.splice(foldData.indexOf(foldLineNext), 1); - }; + } this.toString = function() { var ret = [this.range.toString() + ": [" ]; @@ -232,12 +230,13 @@ function FoldLine(foldData, folds) { this.folds.forEach(function(fold) { ret.push(" " + fold.toString()); }); - ret.push("]"); + ret.push("]") return ret.join("\n"); - }; + } this.idxToPosition = function(idx) { var lastFoldEndColumn = 0; + var fold; for (var i = 0; i < this.folds.length; i++) { var fold = this.folds[i]; @@ -262,7 +261,7 @@ function FoldLine(foldData, folds) { row: this.end.row, column: this.end.column + idx }; - }; + } }).call(FoldLine.prototype); exports.FoldLine = FoldLine; diff --git a/lib/ace/edit_session/folding.js b/lib/ace/edit_session/folding.js index 77c0f22d..3aefea84 100644 --- a/lib/ace/edit_session/folding.js +++ b/lib/ace/edit_session/folding.js @@ -108,18 +108,6 @@ function Folding() { return foundFolds; }; - - this.getFoldsInRangeList = function(ranges) { - if (Array.isArray(ranges)) { - var folds = []; - ranges.forEach(function(range) { - folds = folds.concat(this.getFoldsInRange(range)); - }, this); - } else { - var folds = this.getFoldsInRange(ranges); - } - return folds; - } /* * Returns all folds in the document @@ -128,9 +116,13 @@ function Folding() { var folds = []; var foldLines = this.$foldData; + function addFold(fold) { + folds.push(fold); + } + for (var i = 0; i < foldLines.length; i++) for (var j = 0; j < foldLines[i].folds.length; j++) - folds.push(foldLines[i].folds[j]); + addFold(foldLines[i].folds[j]); return folds; }; @@ -282,19 +274,20 @@ function Folding() { // --- Some checking --- if (!(startRow < endRow || startRow == endRow && startColumn <= endColumn - 2)) - throw new Error("The range has to be at least 2 characters width"); + throw "The range has to be at least 2 characters width"; var startFold = this.getFoldAt(startRow, startColumn, 1); var endFold = this.getFoldAt(endRow, endColumn, -1); if (startFold && endFold == startFold) return startFold.addSubFold(fold); - if (startFold && !startFold.range.isStart(startRow, startColumn)) - this.removeFold(startFold); - - if (endFold && !endFold.range.isEnd(endRow, endColumn)) - this.removeFold(endFold); - + if ( + (startFold && !startFold.range.isStart(startRow, startColumn)) + || (endFold && !endFold.range.isEnd(endRow, endColumn)) + ) { + throw "A fold can't intersect already existing fold" + fold.range + startFold.range; + } + // Check if there are folds in the range we create the new fold for. var folds = this.getFoldsInRange(fold.range); if (folds.length > 0) { @@ -420,7 +413,7 @@ function Folding() { }; this.expandFold = function(fold) { - this.removeFold(fold); + this.removeFold(fold); fold.subFolds.forEach(function(subFold) { fold.restoreRange(subFold); this.addFold(subFold); @@ -448,21 +441,18 @@ function Folding() { range = Range.fromPoints(location, location); else range = location; - - folds = this.getFoldsInRangeList(range); + + folds = this.getFoldsInRange(range); if (expandInner) { this.removeFolds(folds); } else { - var subFolds = folds; - // TODO: might be better to remove and add folds in one go instead of using + // TODO: might need to remove and add folds in one go instead of using // expandFolds several times. - while (subFolds.length) { - this.expandFolds(subFolds); - subFolds = this.getFoldsInRangeList(range); + while (folds.length) { + this.expandFolds(folds); + folds = this.getFoldsInRange(range); } } - if (folds.length) - return folds; }; /* @@ -484,15 +474,15 @@ function Folding() { }; this.getFoldDisplayLine = function(foldLine, endRow, endColumn, startRow, startColumn) { - if (startRow == null) + if (startRow == null) { startRow = foldLine.start.row; - if (startColumn == null) startColumn = 0; - if (endRow == null) + } + + if (endRow == null) { endRow = foldLine.end.row; - if (endColumn == null) endColumn = this.getLine(endRow).length; - + } // Build the textline using the FoldLine walker. var doc = this.doc; @@ -637,8 +627,6 @@ function Folding() { if (depth == undefined) depth = 100000; // JSON.stringify doesn't hanle Infinity var foldWidgets = this.foldWidgets; - if (!foldWidgets) - return; // mode doesn't support folding endRow = endRow || this.getLength(); startRow = startRow || 0; for (var row = startRow; row < endRow; row++) { @@ -648,20 +636,18 @@ function Folding() { continue; var range = this.getFoldWidgetRange(row); + var rangeEndRow = range.end.row; // sometimes range can be incompatible with existing fold // TODO change addFold to return null istead of throwing if (range && range.isMultiLine() - && range.end.row <= endRow + && rangeEndRow <= endRow && range.start.row >= startRow - ) { - row = range.end.row; - try { - // addFold can change the range - var fold = this.addFold("...", range); - if (fold) - fold.collapseChildren = depth; - } catch(e) {} - } + ) try { + var fold = this.addFold("...", range); + fold.collapseChildren = depth; + // addFold can change the range + row = rangeEndRow; + } catch(e) {} } }; @@ -696,8 +682,7 @@ function Folding() { this.$foldMode = foldMode; - this.off('change', this.$updateFoldWidgets); - this.off('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + this.removeListener('change', this.$updateFoldWidgets); this._emit("changeAnnotation"); if (!foldMode || this.$foldStyle == "manual") { @@ -710,9 +695,8 @@ function Folding() { this.getFoldWidgetRange = foldMode.getFoldWidgetRange.bind(foldMode, this, this.$foldStyle); this.$updateFoldWidgets = this.updateFoldWidgets.bind(this); - this.$tokenizerUpdateFoldWidgets = this.tokenizerUpdateFoldWidgets.bind(this); this.on('change', this.$updateFoldWidgets); - this.on('tokenizerUpdate', this.$tokenizerUpdateFoldWidgets); + }; this.getParentFoldRangeData = function (row, ignoreCurrent) { @@ -743,39 +727,25 @@ function Folding() { } this.onFoldWidgetClick = function(row, e) { - e = e.domEvent; - var options = { - children: e.shiftKey, - all: e.ctrlKey || e.metaKey, - siblings: e.altKey - }; - - var range = this.$toggleFoldWidget(row, options); - if (!range) { - var el = (e.target || e.srcElement) - if (el && /ace_fold-widget/.test(el.className)) - el.className += " ace_invalid"; - } - }; - - this.$toggleFoldWidget = function(row, options) { - if (!this.getFoldWidget) - return; var type = this.getFoldWidget(row); var line = this.getLine(row); + e = e.domEvent; + var children = e.shiftKey; + var all = e.ctrlKey || e.metaKey; + var siblings = e.altKey; var dir = type === "end" ? -1 : 1; var fold = this.getFoldAt(row, dir === -1 ? 0 : line.length, dir); if (fold) { - if (options.children || options.all) + if (children || all) this.removeFold(fold); else this.expandFold(fold); return; } - var range = this.getFoldWidgetRange(row, true); + var range = this.getFoldWidgetRange(row); // sometimes singleline folds can be missed by the code above if (range && !range.isMultiLine()) { fold = this.getFoldAt(range.start.row, range.start.column, 1); @@ -785,57 +755,35 @@ function Folding() { } } - if (options.siblings) { + if (siblings) { var data = this.getParentFoldRangeData(row); if (data.range) { var startRow = data.range.start.row + 1; var endRow = data.range.end.row; } - this.foldAll(startRow, endRow, options.all ? 10000 : 0); - } else if (options.children) { - endRow = range ? range.end.row : this.getLength(); - this.foldAll(row + 1, endRow, options.all ? 10000 : 0); + this.foldAll(startRow, endRow, all ? 10000 : 0); + } else if (children) { + var endRow = range ? range.end.row : this.getLength(); + this.foldAll(row + 1, range.end.row, all ? 10000 : 0); } else if (range) { - if (options.all) + if (all) range.collapseChildren = 10000; this.addFold("...", range); } - return range; - }; - - - - this.toggleFoldWidget = function(toggleParent) { - var row = this.selection.getCursor().row; - row = this.getRowFoldStart(row); - var range = this.$toggleFoldWidget(row, {}); - - if (range) - return; - // handle toggleParent - var data = this.getParentFoldRangeData(row, true); - range = data.range || data.firstRange; - - if (range) { - row = range.start.row; - var fold = this.getFoldAt(row, this.getLine(row).length, 1); - - if (fold) { - this.removeFold(fold); - } else { - this.addFold("...", range); - } - } + if (!range) + (e.target || e.srcElement).className += " ace_invalid" }; - this.updateFoldWidgets = function(delta) { - var firstRow = delta.start.row; - var len = delta.end.row - firstRow; + this.updateFoldWidgets = function(e) { + var delta = e.data; + var range = delta.range; + var firstRow = range.start.row; + var len = range.end.row - firstRow; if (len === 0) { this.foldWidgets[firstRow] = null; - } else if (delta.action == 'remove') { + } else if (delta.action == "removeText" || delta.action == "removeLines") { this.foldWidgets.splice(firstRow, len + 1, null); } else { var args = Array(len + 1); @@ -843,13 +791,7 @@ function Folding() { this.foldWidgets.splice.apply(this.foldWidgets, args); } }; - this.tokenizerUpdateFoldWidgets = function(e) { - var rows = e.data; - if (rows.first != rows.last) { - if (this.foldWidgets.length > rows.first) - this.foldWidgets.splice(rows.first, this.foldWidgets.length); - } - } + } exports.Folding = Folding; diff --git a/lib/ace/edit_session_test.js b/lib/ace/edit_session_test.js index 0b904b63..0fbaf3d3 100644 --- a/lib/ace/edit_session_test.js +++ b/lib/ace/edit_session_test.js @@ -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,8 +380,7 @@ 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]); @@ -389,7 +388,6 @@ module.exports = { } EditSession.prototype.$wrapAsCode = true; - EditSession.prototype.$indentedSoftWrap = false; // Basic splitting. computeAndAssert("foo bar foo bar", [ 12 ]); computeAndAssert("foo bar f bar", [ 12 ]); @@ -415,26 +413,16 @@ module.exports = { computeAndAssert("ぁぁ", [1], 2); computeAndAssert(" ぁぁ", [1, 2], 2); computeAndAssert(" ぁ\tぁ", [1, 3], 2); - computeAndAssert(" ぁぁ\tぁ", [2, 4], 4); - computeAndAssert("ぁぁ ぁぁ\tぁ", [3, 6], 6); + computeAndAssert(" ぁぁ\tぁ", [1, 4], 4); // Test wrapping for punctuation. - computeAndAssert(" ab.c;ef++", [2, 4, 6, 8], 2); - computeAndAssert(" ab.c;ef++", [3, 5, 8], 3); + computeAndAssert(" ab.c;ef++", [1, 3, 5, 7, 8], 2); 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() { @@ -442,12 +430,12 @@ module.exports = { session.setTabSize(4); assert.equal(session.getScreenWidth(), 2); - session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']); - session.doc.insertFullLines(1, ["123"]); + session.doc.insertNewLine({row: 0, column: Infinity}); + session.doc.insertLines(1, ["123"]); assert.equal(session.getScreenWidth(), 3); - session.doc.insertMergedLines({row: 0, column: Infinity}, ['', '']); - session.doc.insertFullLines(1, ["\t\t"]); + session.doc.insertNewLine({row: 0, column: Infinity}); + session.doc.insertLines(1, ["\t\t"]); assert.equal(session.getScreenWidth(), 8); @@ -471,9 +459,9 @@ module.exports = { session.setUseWrapMode(true); - document.insertFullLines(0, ["a", "b"]); - document.insertFullLines(2, ["c", "d"]); - document.removeFullLines(1, 2); + document.insertLines(0, ["a", "b"]); + document.insertLines(2, ["c", "d"]); + document.removeLines(1, 2); }, "test wrapMode init has to create wrapData array": function() { @@ -949,7 +937,7 @@ module.exports = { fail = true; } if (fail != shouldFail) { - throw new Error("Expected to get an exception"); + throw "Expected to get an exception"; } } diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 5da8a961..c098e792 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -48,7 +48,6 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter; var CommandManager = require("./commands/command_manager").CommandManager; var defaultCommands = require("./commands/default_commands").commands; var config = require("./config"); -var TokenIterator = require("./token_iterator").TokenIterator; /** * The main entry point into the Ace functionality. @@ -94,8 +93,7 @@ var Editor = function(renderer, session) { this._$emitInputEvent = lang.delayedCall(function() { this._signal("input", {}); - if (this.session && this.session.bgTokenizer) - this.session.bgTokenizer.scheduleStart(); + this.session.bgTokenizer && this.session.bgTokenizer.scheduleStart(); }.bind(this)); this.on("change", function(_, _self) { @@ -104,7 +102,7 @@ var Editor = function(renderer, session) { this.setSession(session || new EditSession("")); config.resetOptions(this); - config._signal("editor", this); + config._emit("editor", this); }; (function(){ @@ -112,11 +110,34 @@ var Editor = function(renderer, session) { oop.implement(this, EventEmitter); this.$initOperationListeners = function() { - function last(a) {return a[a.length - 1]} + function last(a) {return a[a.length - 1]}; this.selections = []; - this.commands.on("exec", this.startOperation.bind(this), true); - this.commands.on("afterExec", this.endOperation.bind(this), true); + this.commands.on("exec", function(e) { + this.startOperation(e); + + var command = e.command; + if (command.group == "fileJump") { + var prev = this.prevOp; + if (!prev || prev.command.group != "fileJump") { + this.lastFileJumpPos = last(this.selections) + } + } else { + this.lastFileJumpPos = null; + } + }.bind(this), true); + + this.commands.on("afterExec", function(e) { + var command = e.command; + + if (command.group == "fileJump") { + if (this.lastFileJumpPos && !this.curOp.selectionChanged) { + this.selection.fromJSON(this.lastFileJumpPos); + return + } + } + this.endOperation(e); + }.bind(this), true); this.$opResetTimer = lang.delayedCall(this.endOperation.bind(this)); @@ -129,7 +150,7 @@ var Editor = function(renderer, session) { this.curOp || this.startOperation(); this.curOp.selectionChanged = true; }.bind(this), true); - }; + } this.curOp = null; this.prevOp = {}; @@ -147,61 +168,26 @@ var Editor = function(renderer, session) { this.$opResetTimer.schedule(); this.curOp = { command: commadEvent.command || {}, - args: commadEvent.args, - scrollTop: this.renderer.scrollTop + args: commadEvent.args }; - if (this.curOp.command.name && this.curOp.command.scrollIntoView !== undefined) - this.$blockScrolling++; + + this.selections.push(this.selection.toJSON()); }; - this.endOperation = function(e) { + this.endOperation = function() { if (this.curOp) { - if (e && e.returnValue === false) - return this.curOp = null; - this._signal("beforeEndOperation"); - var command = this.curOp.command; - if (command.name && this.$blockScrolling > 0) - this.$blockScrolling--; - 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; - case "animate": - case "cursor": - this.renderer.scrollCursorIntoView(); - break; - case "selectionPart": - var range = this.selection.getRange(); - var config = this.renderer.layerConfig; - if (range.start.row >= config.lastRow || range.end.row <= config.firstRow) { - this.renderer.scrollSelectionIntoView(this.selection.anchor, this.selection.lead); - } - break; - default: - break; - } - if (scrollIntoView == "animate") - this.renderer.animateScrolling(this.curOp.scrollTop); - } - this.prevOp = this.curOp; this.curOp = null; } }; - // TODO use property on commands instead of this - this.$mergeableCommands = ["backspace", "del", "insertstring"]; this.$historyTracker = function(e) { if (!this.$mergeUndoDeltas) return; + var prev = this.prevOp; - var mergeableCommands = this.$mergeableCommands; + var mergeableCommands = ["backspace", "del", "insertstring"]; // previous command was the same var shouldMerge = prev.command && (e.command.name == prev.command.name); if (e.command.name == "insertstring") { @@ -211,12 +197,12 @@ var Editor = function(renderer, session) { shouldMerge = shouldMerge && this.mergeNextCommand // previous command allows to coalesce with - && (!/\s/.test(text) || /\s/.test(prev.args)); // previous insertion was of same type + && (!/\s/.test(text) || /\s/.test(prev.args)) // previous insertion was of same type this.mergeNextCommand = true; } else { shouldMerge = shouldMerge - && mergeableCommands.indexOf(e.command.name) !== -1; // the command is mergeable + && mergeableCommands.indexOf(e.command.name) !== -1// the command is mergeable } if ( @@ -236,20 +222,21 @@ var Editor = function(renderer, session) { * Sets a new key handler, such as "vim" or "windows". * @param {String} keyboardHandler The new key handler * + * **/ - this.setKeyboardHandler = function(keyboardHandler, cb) { - if (keyboardHandler && typeof keyboardHandler === "string") { + this.setKeyboardHandler = function(keyboardHandler) { + if (!keyboardHandler) { + this.keyBinding.setKeyboardHandler(null); + } else if (typeof keyboardHandler == "string") { this.$keybindingId = keyboardHandler; var _self = this; config.loadModule(["keybinding", keyboardHandler], function(module) { if (_self.$keybindingId == keyboardHandler) _self.keyBinding.setKeyboardHandler(module && module.handler); - cb && cb(); }); } else { this.$keybindingId = null; this.keyBinding.setKeyboardHandler(keyboardHandler); - cb && cb(); } }; @@ -269,22 +256,20 @@ var Editor = function(renderer, session) { * @event changeSession * @param {Object} e An object with two properties, `oldSession` and `session`, that represent the old and new [[EditSession]]s. * + * **/ /** * Sets a new editsession to use. This method also emits the `'changeSession'` event. * @param {EditSession} session The new session to use * + * **/ this.setSession = function(session) { if (this.session == session) return; - - // make sure operationEnd events are not emitted to wrong session - if (this.curOp) this.endOperation(); - this.curOp = {}; - var oldSession = this.session; - if (oldSession) { + if (this.session) { + var oldSession = this.session; this.session.removeEventListener("change", this.$onDocumentChange); this.session.removeEventListener("changeMode", this.$onChangeMode); this.session.removeEventListener("tokenizerUpdate", this.$onTokenizerUpdate); @@ -306,85 +291,76 @@ var Editor = function(renderer, session) { } this.session = session; - if (session) { - this.$onDocumentChange = this.onDocumentChange.bind(this); - session.addEventListener("change", this.$onDocumentChange); - this.renderer.setSession(session); - - this.$onChangeMode = this.onChangeMode.bind(this); - session.addEventListener("changeMode", this.$onChangeMode); - - this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); - session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate); - - this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); - session.addEventListener("changeTabSize", this.$onChangeTabSize); - - this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); - session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit); - - this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); - session.addEventListener("changeWrapMode", this.$onChangeWrapMode); - - this.$onChangeFold = this.onChangeFold.bind(this); - session.addEventListener("changeFold", this.$onChangeFold); - - this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); - this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker); - - this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); - this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker); - - this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); - this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint); - - this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); - this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation); - - this.$onCursorChange = this.onCursorChange.bind(this); - this.session.addEventListener("changeOverwrite", this.$onCursorChange); - - this.$onScrollTopChange = this.onScrollTopChange.bind(this); - this.session.addEventListener("changeScrollTop", this.$onScrollTopChange); - - this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); - this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange); - - this.selection = session.getSelection(); - this.selection.addEventListener("changeCursor", this.$onCursorChange); - - this.$onSelectionChange = this.onSelectionChange.bind(this); - this.selection.addEventListener("changeSelection", this.$onSelectionChange); - - this.onChangeMode(); - - this.$blockScrolling += 1; - this.onCursorChange(); - this.$blockScrolling -= 1; - - this.onScrollTopChange(); - this.onScrollLeftChange(); - this.onSelectionChange(); - this.onChangeFrontMarker(); - this.onChangeBackMarker(); - this.onChangeBreakpoint(); - this.onChangeAnnotation(); - this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); - this.renderer.updateFull(); - } else { - this.selection = null; - this.renderer.setSession(session); - } - this._signal("changeSession", { + this.$onDocumentChange = this.onDocumentChange.bind(this); + session.addEventListener("change", this.$onDocumentChange); + this.renderer.setSession(session); + + this.$onChangeMode = this.onChangeMode.bind(this); + session.addEventListener("changeMode", this.$onChangeMode); + + this.$onTokenizerUpdate = this.onTokenizerUpdate.bind(this); + session.addEventListener("tokenizerUpdate", this.$onTokenizerUpdate); + + this.$onChangeTabSize = this.renderer.onChangeTabSize.bind(this.renderer); + session.addEventListener("changeTabSize", this.$onChangeTabSize); + + this.$onChangeWrapLimit = this.onChangeWrapLimit.bind(this); + session.addEventListener("changeWrapLimit", this.$onChangeWrapLimit); + + this.$onChangeWrapMode = this.onChangeWrapMode.bind(this); + session.addEventListener("changeWrapMode", this.$onChangeWrapMode); + + this.$onChangeFold = this.onChangeFold.bind(this); + session.addEventListener("changeFold", this.$onChangeFold); + + this.$onChangeFrontMarker = this.onChangeFrontMarker.bind(this); + this.session.addEventListener("changeFrontMarker", this.$onChangeFrontMarker); + + this.$onChangeBackMarker = this.onChangeBackMarker.bind(this); + this.session.addEventListener("changeBackMarker", this.$onChangeBackMarker); + + this.$onChangeBreakpoint = this.onChangeBreakpoint.bind(this); + this.session.addEventListener("changeBreakpoint", this.$onChangeBreakpoint); + + this.$onChangeAnnotation = this.onChangeAnnotation.bind(this); + this.session.addEventListener("changeAnnotation", this.$onChangeAnnotation); + + this.$onCursorChange = this.onCursorChange.bind(this); + this.session.addEventListener("changeOverwrite", this.$onCursorChange); + + this.$onScrollTopChange = this.onScrollTopChange.bind(this); + this.session.addEventListener("changeScrollTop", this.$onScrollTopChange); + + this.$onScrollLeftChange = this.onScrollLeftChange.bind(this); + this.session.addEventListener("changeScrollLeft", this.$onScrollLeftChange); + + this.selection = session.getSelection(); + this.selection.addEventListener("changeCursor", this.$onCursorChange); + + this.$onSelectionChange = this.onSelectionChange.bind(this); + this.selection.addEventListener("changeSelection", this.$onSelectionChange); + + this.onChangeMode(); + + this.$blockScrolling += 1; + this.onCursorChange(); + this.$blockScrolling -= 1; + + this.onScrollTopChange(); + this.onScrollLeftChange(); + this.onSelectionChange(); + this.onChangeFrontMarker(); + this.onChangeBackMarker(); + this.onChangeBreakpoint(); + this.onChangeAnnotation(); + this.session.getUseWrapMode() && this.renderer.adjustWrapLimit(); + this.renderer.updateFull(); + + this._emit("changeSession", { session: session, oldSession: oldSession }); - - this.curOp = null; - - oldSession && oldSession._signal("changeEditor", {oldEditor: this}); - session && session._signal("changeEditor", {editor: this}); }; /** @@ -449,10 +425,11 @@ var Editor = function(renderer, session) { /** * {:VirtualRenderer.setTheme} * @param {String} theme The path to a theme - * @param {Function} cb optional callback called when theme is loaded + * + * **/ - this.setTheme = function(theme, cb) { - this.renderer.setTheme(theme, cb); + this.setTheme = function(theme) { + this.renderer.setTheme(theme); }; /** @@ -517,105 +494,15 @@ var Editor = function(renderer, session) { this.$highlightPending = true; setTimeout(function() { self.$highlightPending = false; - var session = self.session; - if (!session || !session.bgTokenizer) return; - var pos = session.findMatchingBracket(self.getCursorPosition()); + + var pos = self.session.findMatchingBracket(self.getCursorPosition()); if (pos) { - var range = new Range(pos.row, pos.column, pos.row, pos.column + 1); - } else if (session.$mode.getMatching) { - var range = session.$mode.getMatching(self.session); + var range = new Range(pos.row, pos.column, pos.row, pos.column+1); + } else if (self.session.$mode.getMatching) { + var range = self.session.$mode.getMatching(self.session); } if (range) - session.$bracketHighlight = session.addMarker(range, "ace_bracket", "text"); - }, 50); - }; - - // todo: move to mode.getMatching - this.$highlightTags = function() { - if (this.$highlightTagPending) - return; - - // perform highlight async to not block the browser during navigation - var self = this; - this.$highlightTagPending = true; - setTimeout(function() { - self.$highlightTagPending = false; - - var session = self.session; - if (!session || !session.bgTokenizer) return; - - var pos = self.getCursorPosition(); - var iterator = new TokenIterator(self.session, pos.row, pos.column); - var token = iterator.getCurrentToken(); - - if (!token || !/\b(?:tag-open|tag-name)/.test(token.type)) { - session.removeMarker(session.$tagHighlight); - session.$tagHighlight = null; - return; - } - - if (token.type.indexOf("tag-open") != -1) { - token = iterator.stepForward(); - if (!token) - return; - } - - var tag = token.value; - var depth = 0; - var prevToken = iterator.stepBackward(); - - if (prevToken.value == '<'){ - //find closing tag - do { - prevToken = token; - token = iterator.stepForward(); - - if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { - if (prevToken.value === '<'){ - depth++; - } else if (prevToken.value === '= 0); - } else { - //find opening tag - do { - token = prevToken; - prevToken = iterator.stepBackward(); - - if (token && token.value === tag && token.type.indexOf('tag-name') !== -1) { - if (prevToken.value === '<') { - depth++; - } else if (prevToken.value === ' 1)) + if (this.renderer.$maxLines && this.session.getLength() === 1) highlight = false; } @@ -762,7 +648,7 @@ var Editor = function(renderer, session) { session.$highlightLineMarker.start.row = highlight.row; session.$highlightLineMarker.end.row = highlight.row; session.$highlightLineMarker.start.column = highlight.column; - session._signal("changeBackMarker"); + session._emit("changeBackMarker"); } }; @@ -782,10 +668,10 @@ var Editor = function(renderer, session) { this.$updateHighlightActiveLine(); } - var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp(); + var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp() this.session.highlight(re); - this._signal("changeSelection"); + this._emit("changeSelection"); }; this.$getSelectionHighLightRegexp = function() { @@ -905,7 +791,7 @@ var Editor = function(renderer, session) { /** * Emitted when text is pasted. * @event paste - * @param {Object} an object which contains one property, `text`, that represents the text to be pasted. Editing this property will alter the text that is pasted. + * @param {String} text The pasted text * * **/ @@ -915,50 +801,31 @@ var Editor = function(renderer, session) { * * **/ - 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); - var text = e.text; - if (!this.inMultiSelectMode || this.inVirtualSelectionMode) { - this.insert(text); - } else { - var lines = text.split(/\r\n|\r|\n/); - var ranges = this.selection.rangeList.ranges; - - if (lines.length > ranges.length || lines.length < 2 || !lines[1]) - return this.commands.exec("insertstring", this, text); - - for (var i = ranges.length; i--;) { - var range = ranges[i]; - if (!range.isEmpty()) - this.session.remove(range); - - this.session.insert(range.start, lines[i]); - } - } + this.onPaste = function(text) { + // todo this should change when paste becomes a command + if (this.$readOnly) + return; + this._emit("paste", text); + this.insert(text); }; + this.execCommand = function(command, args) { - return this.commands.exec(command, this, args); + this.commands.exec(command, this, args); }; /** * Inserts `text` into wherever the cursor is pointing. * @param {String} text The new text to add * + * **/ - this.insert = function(text, pasted) { + this.insert = function(text) { var session = this.session; var mode = session.getMode(); var cursor = this.getCursorPosition(); - if (this.getBehavioursEnabled() && !pasted) { + if (this.getBehavioursEnabled()) { // Get a transform if the current mode wants one. var transform = mode.transformAction(session.getState(cursor.row), 'insertion', this, session, text); if (transform) { @@ -987,7 +854,7 @@ var Editor = function(renderer, session) { } if (text == "\n" || text == "\r\n") { - var line = session.getLine(cursor.row); + var line = session.getLine(cursor.row) if (cursor.column > line.search(/\S|$/)) { var d = line.substr(cursor.column).search(/\S|$/); session.doc.removeInLine(cursor.row, cursor.column, cursor.column + d); @@ -1135,7 +1002,6 @@ var Editor = function(renderer, session) { this.getHighlightGutterLine = function() { return this.getOption("highlightGutterLine"); }; - /** * Determines if the currently selected word should be highlighted. * @param {Boolean} shouldHighlight Set to `true` to highlight the currently selected word @@ -1297,7 +1163,7 @@ var Editor = function(renderer, session) { }; /** - * Removes the current selection or one character. + * Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace. * @param {String} dir The direction of the deletion to occur, either "left" or "right" * **/ @@ -1315,12 +1181,12 @@ var Editor = function(renderer, session) { var state = session.getState(range.start.row); var new_range = session.getMode().transformAction(state, 'deletion', this, session, range); - if (range.end.column === 0) { + if (range.end.column == 0) { var text = session.getTextRange(range); if (text[text.length - 1] == "\n") { - var line = session.getLine(range.end.row); + var line = session.getLine(range.end.row) if (/^\s+$/.test(line)) { - range.end.column = line.length; + range.end.column = line.length } } } @@ -1466,7 +1332,7 @@ var Editor = function(renderer, session) { session.indentRows(rows.first, rows.last, "\t"); return; } else if (range.start.column < range.end.column) { - var text = session.getTextRange(range); + var text = session.getTextRange(range) if (!/^\s+$/.test(text)) { var rows = this.$getSelectedRows(); session.indentRows(rows.first, rows.last, "\t"); @@ -1474,7 +1340,7 @@ var Editor = function(renderer, session) { } } - var line = session.getLine(range.start.row); + var line = session.getLine(range.start.row) var position = range.start; var size = session.getTabSize(); var column = session.documentToScreenColumn(position.row, position.column); @@ -1557,19 +1423,19 @@ var Editor = function(renderer, session) { * Works like [[EditSession.getTokenAt]], except it returns a number. * @returns {Number} **/ - this.getNumberAt = function(row, column) { - var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g; - _numberRx.lastIndex = 0; + this.getNumberAt = function( row, column ) { + var _numberRx = /[\-]?[0-9]+(?:\.[0-9]+)?/g + _numberRx.lastIndex = 0 - var s = this.session.getLine(row); + var s = this.session.getLine(row) while (_numberRx.lastIndex < column) { - var m = _numberRx.exec(s); + var m = _numberRx.exec(s) if(m.index <= column && m.index+m[0].length >= column){ var number = { value: m[0], start: m.index, end: m.index+m[0].length - }; + } return number; } } @@ -1629,7 +1495,15 @@ var Editor = function(renderer, session) { **/ this.removeLines = function() { var rows = this.$getSelectedRows(); - this.session.removeFullLines(rows.first, rows.last); + 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.clearSelection(); }; @@ -1647,7 +1521,7 @@ var Editor = function(renderer, session) { range.start = point; range.end = endPoint; - sel.setSelectionRange(range, reverse); + sel.setSelectionRange(range, reverse) } }; @@ -1658,7 +1532,9 @@ var Editor = function(renderer, session) { * @related EditSession.moveLinesUp **/ this.moveLinesDown = function() { - this.$moveLines(1, false); + this.$moveLines(function(firstRow, lastRow) { + return this.session.moveLinesDown(firstRow, lastRow); + }); }; /** @@ -1667,7 +1543,9 @@ var Editor = function(renderer, session) { * @related EditSession.moveLinesDown **/ this.moveLinesUp = function() { - this.$moveLines(-1, false); + this.$moveLines(function(firstRow, lastRow) { + return this.session.moveLinesUp(firstRow, lastRow); + }); }; /** @@ -1691,7 +1569,10 @@ var Editor = function(renderer, session) { * **/ this.copyLinesUp = function() { - this.$moveLines(-1, true); + this.$moveLines(function(firstRow, lastRow) { + this.session.duplicateLines(firstRow, lastRow); + return 0; + }); }; /** @@ -1701,61 +1582,51 @@ var Editor = function(renderer, session) { * **/ this.copyLinesDown = function() { - this.$moveLines(1, true); + this.$moveLines(function(firstRow, lastRow) { + return this.session.duplicateLines(firstRow, lastRow); + }); }; /** - * for internal use - * @ignore + * Executes a specific function, which can be anything that manipulates selected lines, such as copying them, duplicating them, or shifting them. + * @param {Function} mover A method to call on each selected row + * * **/ - this.$moveLines = function(dir, copy) { - var rows, moved; + this.$moveLines = function(mover) { var selection = this.selection; if (!selection.inMultiSelectMode || this.inVirtualSelectionMode) { var range = selection.toOrientedRange(); - rows = this.$getSelectedRows(range); - moved = this.session.$moveLines(rows.first, rows.last, copy ? 0 : dir); - if (copy && dir == -1) moved = 0; - range.moveBy(moved, 0); + var rows = this.$getSelectedRows(range); + var linesMoved = mover.call(this, rows.first, rows.last); + range.moveBy(linesMoved, 0); selection.fromOrientedRange(range); } else { var ranges = selection.rangeList.ranges; selection.rangeList.detach(this.session); - this.inVirtualSelectionMode = true; - - var diff = 0; - var totalDiff = 0; - var l = ranges.length; - for (var i = 0; i < l; i++) { + + for (var i = ranges.length; i--; ) { var rangeIndex = i; - ranges[i].moveBy(diff, 0); - rows = this.$getSelectedRows(ranges[i]); - var first = rows.first; - var last = rows.last; - while (++i < l) { - if (totalDiff) ranges[i].moveBy(totalDiff, 0); - var subRows = this.$getSelectedRows(ranges[i]); - if (copy && subRows.first != last) + var rows = ranges[i].collapseRows(); + var last = rows.end.row; + var first = rows.start.row; + while (i--) { + var rows = ranges[i].collapseRows(); + if (first - rows.end.row <= 1) + first = rows.end.row; + else break; - else if (!copy && subRows.first > last + 1) - break; - last = subRows.last; } - i--; - diff = this.session.$moveLines(first, last, copy ? 0 : dir); - if (copy && dir == -1) rangeIndex = i + 1; - while (rangeIndex <= i) { - ranges[rangeIndex].moveBy(diff, 0); - rangeIndex++; + i++; + + var linesMoved = mover.call(this, first, last); + while (rangeIndex >= i) { + ranges[rangeIndex].moveBy(linesMoved, 0); + rangeIndex--; } - if (!copy) diff = 0; - totalDiff += diff; } - selection.fromOrientedRange(selection.ranges[0]); selection.rangeList.attach(this.session); - this.inVirtualSelectionMode = false; } }; @@ -1768,12 +1639,12 @@ var Editor = function(renderer, session) { * * @returns {Object} **/ - this.$getSelectedRows = function(range) { - range = (range || this.getSelectionRange()).collapseRows(); + this.$getSelectedRows = function() { + var range = this.getSelectionRange().collapseRows(); return { - first: this.session.getRowFoldStart(range.start.row), - last: this.session.getRowFoldEnd(range.end.row) + first: range.start.row, + last: range.end.row }; }; @@ -1844,11 +1715,11 @@ var Editor = function(renderer, session) { var rows = dir * Math.floor(config.height / config.lineHeight); this.$blockScrolling++; - if (select === true) { + if (select == true) { this.selection.$moveSelection(function(){ this.moveCursorBy(rows, 0); }); - } else if (select === false) { + } else if (select == false) { this.selection.moveCursorBy(rows, 0); this.selection.clearSelection(); } @@ -1935,7 +1806,7 @@ var Editor = function(renderer, session) { var pos = { row: Math.floor(range.start.row + (range.end.row - range.start.row) / 2), column: Math.floor(range.start.column + (range.end.column - range.start.column) / 2) - }; + } this.renderer.alignCursor(pos, 0.5); }; @@ -2014,168 +1885,36 @@ var Editor = function(renderer, session) { }; /** - * Moves the cursor's row and column to the next matching bracket or HTML tag. + * Moves the cursor's row and column to the next matching bracket. * **/ - this.jumpToMatching = function(select, expand) { + this.jumpToMatching = function(select) { var cursor = this.getCursorPosition(); - var iterator = new TokenIterator(this.session, cursor.row, cursor.column); - var prevToken = iterator.getCurrentToken(); - var token = prevToken || iterator.stepForward(); - if (!token) return; - - //get next closing tag or bracket - var matchType; - var found = false; - var depth = {}; - var i = cursor.column - token.start; - var bracketType; - var brackets = { - ")": "(", - "(": "(", - "]": "[", - "[": "[", - "{": "{", - "}": "{" - }; - - do { - if (token.value.match(/[{}()\[\]]/g)) { - for (; i < token.value.length && !found; i++) { - if (!brackets[token.value[i]]) { - continue; - } - - bracketType = brackets[token.value[i]] + '.' + token.type.replace("rparen", "lparen"); - - if (isNaN(depth[bracketType])) { - depth[bracketType] = 0; - } - - switch (token.value[i]) { - case '(': - case '[': - case '{': - depth[bracketType]++; - break; - case ')': - case ']': - case '}': - depth[bracketType]--; - - if (depth[bracketType] === -1) { - matchType = 'bracket'; - found = true; - } - break; - } - } - } - else if (token && token.type.indexOf('tag-name') !== -1) { - if (isNaN(depth[token.value])) { - depth[token.value] = 0; - } - - if (prevToken.value === '<') { - depth[token.value]++; - } - else if (prevToken.value === '= 0; --i) { if(this.$tryReplace(ranges[i], replacement)) { @@ -2498,7 +2245,7 @@ var Editor = function(renderer, session) { var scrollTop = this.renderer.scrollTop; this.renderer.scrollSelectionIntoView(range.start, range.end, 0.5); - if (animate !== false) + if (animate != false) this.renderer.animateScrolling(scrollTop); }; @@ -2530,10 +2277,7 @@ var Editor = function(renderer, session) { **/ this.destroy = function() { this.renderer.destroy(); - this._signal("destroy", this); - if (this.session) { - this.session.destroy(); - } + this._emit("destroy", this); }; /** @@ -2541,7 +2285,7 @@ var Editor = function(renderer, session) { * @param {Boolean} enable default true **/ this.setAutoScrollEditorIntoView = function(enable) { - if (!enable) + if (enable === false) return; var rect; var self = this; @@ -2560,9 +2304,7 @@ var Editor = function(renderer, session) { rect = self.renderer.container.getBoundingClientRect(); }); var onAfterRender = this.renderer.on("afterRender", function() { - if (shouldScroll && rect && (self.isFocused() - || self.searchBox && self.searchBox.isFocused()) - ) { + if (shouldScroll && rect && self.isFocused()) { var renderer = self.renderer; var pos = renderer.$cursorLayer.$pixelPos; var config = renderer.layerConfig; @@ -2585,7 +2327,7 @@ var Editor = function(renderer, session) { } }); this.setAutoScrollEditorIntoView = function(enable) { - if (enable) + if (enable === true) return; delete this.setAutoScrollEditorIntoView; this.removeEventListener("changeSelection", onChangeSelection); @@ -2600,9 +2342,8 @@ var Editor = function(renderer, session) { var cursorLayer = this.renderer.$cursorLayer; if (!cursorLayer) return; - cursorLayer.setSmoothBlinking(/smooth/.test(style)); + cursorLayer.setSmoothBlinking(style == "smooth"); cursorLayer.isBlinking = !this.$readOnly && style != "wide"; - dom.setCssClass(cursorLayer.element, "ace_slim-cursors", /slim/.test(style)); }; }).call(Editor.prototype); @@ -2613,7 +2354,7 @@ config.defineOptions(Editor.prototype, "editor", { selectionStyle: { set: function(style) { this.onSelectionChange(); - this._signal("changeSelectionStyle", {data: style}); + this._emit("changeSelectionStyle", {data: style}); }, initialValue: "line" }, @@ -2626,11 +2367,7 @@ config.defineOptions(Editor.prototype, "editor", { initialValue: true }, readOnly: { - set: function(readOnly) { - // disabled to not break vim mode! - // this.textInput.setReadOnly(readOnly); - this.$resetCursorStyle(); - }, + set: function(readOnly) { this.$resetCursorStyle(); }, initialValue: false }, cursorStyle: { @@ -2644,9 +2381,6 @@ config.defineOptions(Editor.prototype, "editor", { }, behavioursEnabled: {initialValue: true}, wrapBehavioursEnabled: {initialValue: true}, - autoScrollEditorIntoView: { - set: function(val) {this.setAutoScrollEditorIntoView(val)} - }, hScrollBarAlwaysVisible: "renderer", vScrollBarAlwaysVisible: "renderer", @@ -2658,7 +2392,6 @@ config.defineOptions(Editor.prototype, "editor", { printMargin: "renderer", fadeFoldWidgets: "renderer", showFoldWidgets: "renderer", - showLineNumbers: "renderer", showGutter: "renderer", displayIndentGuides: "renderer", fontSize: "renderer", @@ -2667,13 +2400,11 @@ config.defineOptions(Editor.prototype, "editor", { minLines: "renderer", scrollPastEnd: "renderer", fixedWidthGutter: "renderer", - theme: "renderer", scrollSpeed: "$mouseHandler", dragDelay: "$mouseHandler", dragEnabled: "$mouseHandler", focusTimout: "$mouseHandler", - tooltipFollowsMouse: "$mouseHandler", firstLineNumber: "session", overwrite: "session", @@ -2682,9 +2413,7 @@ config.defineOptions(Editor.prototype, "editor", { useSoftTabs: "session", tabSize: "session", wrap: "session", - indentedSoftWrap: "session", - foldStyle: "session", - mode: "session" + foldStyle: "session" }); exports.Editor = Editor; diff --git a/lib/ace/ext/beautify.js b/lib/ace/ext/beautify.js deleted file mode 100644 index d0fa1799..00000000 --- a/lib/ace/ext/beautify.js +++ /dev/null @@ -1,57 +0,0 @@ -/* ***** 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 ***** */ - -// [WIP] - -define(function(require, exports, module) { -"use strict"; -var TokenIterator = require("ace/token_iterator").TokenIterator; - -var phpTransform = require("./beautify/php_rules").transform; - -exports.beautify = function(session) { - var iterator = new TokenIterator(session, 0, 0); - var token = iterator.getCurrentToken(); - - var context = session.$modeId.split("/").pop(); - - var code = phpTransform(iterator, context); - session.doc.setValue(code); -}; - -exports.commands = [{ - name: "beautify", - exec: function(editor) { - exports.beautify(editor.session); - }, - bindKey: "Ctrl-Shift-B" -}] - -}); \ No newline at end of file diff --git a/lib/ace/ext/beautify/php_rules.js b/lib/ace/ext/beautify/php_rules.js deleted file mode 100644 index 9a5bed36..00000000 --- a/lib/ace/ext/beautify/php_rules.js +++ /dev/null @@ -1,366 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { -"use strict"; -var TokenIterator = require("ace/token_iterator").TokenIterator; -exports.newLines = [{ - type: 'support.php_tag', - value: '' -}, { - type: 'paren.lparen', - value: '{', - indent: true -}, { - type: 'paren.rparen', - breakBefore: true, - value: '}', - indent: false -}, { - type: 'paren.rparen', - breakBefore: true, - value: '})', - indent: false, - dontBreak: true -}, { - type: 'comment' -}, { - type: 'text', - value: ';' -}, { - type: 'text', - value: ':', - context: 'php' -}, { - type: 'keyword', - value: 'case', - indent: true, - dontBreak: true -}, { - type: 'keyword', - value: 'default', - indent: true, - dontBreak: true -}, { - type: 'keyword', - value: 'break', - indent: false, - dontBreak: true -}, { - type: 'punctuation.doctype.end', - value: '>' -}, { - type: 'meta.tag.punctuation.end', - value: '>' -}, { - type: 'meta.tag.punctuation.begin', - value: '<', - blockTag: true, - indent: true, - dontBreak: true -}, { - type: 'meta.tag.punctuation.begin', - value: '' ){ - context = 'php'; - } - else if( token.type == 'support.php_tag' && token.value == '?>' ){ - context = 'html'; - } - //css - else if( token.type == 'meta.tag.name.style' && context != 'css' ){ - context = 'css'; - } - else if( token.type == 'meta.tag.name.style' && context == 'css' ){ - context = 'html'; - } - //js - else if( token.type == 'meta.tag.name.script' && context != 'js' ){ - context = 'js'; - } - else if( token.type == 'meta.tag.name.script' && context == 'js' ){ - context = 'html'; - } - - nextToken = iterator.stepForward(); - - //tag name - if (nextToken && nextToken.type.indexOf('meta.tag.name') == 0) { - nextTag = nextToken.value; - } - - //don't linebreak - if ( lastToken.type == 'support.php_tag' && lastToken.value == '' ) { - dontBreak = false; - } - - //next token - lastTag = tag; - - lastToken = token; - - token = nextToken; - - if (token===null) { - break; - } - } - - return code; -}; - - - -}); \ No newline at end of file diff --git a/lib/ace/ext/chromevox.js b/lib/ace/ext/chromevox.js index 52a180d4..9f7a7996 100644 --- a/lib/ace/ext/chromevox.js +++ b/lib/ace/ext/chromevox.js @@ -578,14 +578,15 @@ var onSelectionChange = function(evt) { * and deleting text. * @param {!Event} evt The event. */ -var onChange = function(delta) { +var onChange = function(evt) { + var data = evt.data; switch (data.action) { - case 'remove': + case 'removeText': cvox.Api.speak(data.text, 0, DELETED_PROP); /* Let the future cursor change event know it's from text change. */ changed = true; break; - case 'insert': + case 'insertText': cvox.Api.speak(data.text, 0); /* Let the future cursor change event know it's from text change. */ changed = true; diff --git a/lib/ace/ext/elastic_tabstops_lite.js b/lib/ace/ext/elastic_tabstops_lite.js index 0f89423a..9901c5df 100644 --- a/lib/ace/ext/elastic_tabstops_lite.js +++ b/lib/ace/ext/elastic_tabstops_lite.js @@ -44,12 +44,13 @@ var ElasticTabstopsLite = function(editor) { this.onExec = function() { recordChanges = true; }; - this.onChange = function(delta) { + this.onChange = function(e) { + var range = e.data.range if (recordChanges) { - if (changedRows.indexOf(delta.start.row) == -1) - changedRows.push(delta.start.row); - if (delta.end.row != delta.start.row) - changedRows.push(delta.end.row); + if (changedRows.indexOf(range.start.row) == -1) + changedRows.push(range.start.row); + if (range.end.row != range.start.row) + changedRows.push(range.end.row); } }; }; diff --git a/lib/ace/ext/emmet.js b/lib/ace/ext/emmet.js index 4faacef2..6647da40 100644 --- a/lib/ace/ext/emmet.js +++ b/lib/ace/ext/emmet.js @@ -34,7 +34,15 @@ var HashHandler = require("ace/keyboard/hash_handler").HashHandler; var Editor = require("ace/editor").Editor; var snippetManager = require("ace/snippets").snippetManager; var Range = require("ace/range").Range; -var emmet, emmetPath; +var emmet; + +Editor.prototype.indexToPosition = function(index) { + return this.session.doc.indexToPosition(index); +}; + +Editor.prototype.positionToIndex = function(pos) { + return this.session.doc.positionToIndex(pos); +}; /** * Implementation of {@link IEmmetEditor} interface for Ace @@ -64,10 +72,9 @@ AceEmmetEditor.prototype = { getSelectionRange: function() { // TODO should start be caret position instead? var range = this.ace.getSelectionRange(); - var doc = this.ace.session.doc; return { - start: doc.positionToIndex(range.start), - end: doc.positionToIndex(range.end) + start: this.ace.positionToIndex(range.start), + end: this.ace.positionToIndex(range.end) }; }, @@ -84,10 +91,9 @@ AceEmmetEditor.prototype = { * editor.createSelection(15); */ createSelection: function(start, end) { - var doc = this.ace.session.doc; this.ace.selection.setRange({ - start: doc.indexToPosition(start), - end: doc.indexToPosition(end) + start: this.ace.indexToPosition(start), + end: this.ace.indexToPosition(end) }); }, @@ -100,10 +106,9 @@ AceEmmetEditor.prototype = { * alert(range.start + ', ' + range.end); */ getCurrentLineRange: function() { - var ace = this.ace; - var row = ace.getCursorPosition().row; - var lineLength = ace.session.getLine(row).length; - var index = ace.session.doc.positionToIndex({row: row, column: 0}); + var row = this.ace.getCursorPosition().row; + var lineLength = this.ace.session.getLine(row).length; + var index = this.ace.positionToIndex({row: row, column: 0}); return { start: index, end: index + lineLength @@ -116,7 +121,7 @@ AceEmmetEditor.prototype = { */ getCaretPos: function(){ var pos = this.ace.getCursorPosition(); - return this.ace.session.doc.positionToIndex(pos); + return this.ace.positionToIndex(pos); }, /** @@ -124,8 +129,9 @@ AceEmmetEditor.prototype = { * @param {Number} index Caret position */ setCaretPos: function(index){ - var pos = this.ace.session.doc.indexToPosition(index); - this.ace.selection.moveToPosition(pos); + var pos = this.ace.indexToPosition(index); + this.ace.clearSelection(); + this.ace.selection.moveCursorToPosition(pos); }, /** @@ -164,15 +170,14 @@ AceEmmetEditor.prototype = { start = 0; var editor = this.ace; - var doc = editor.session.doc; - var range = Range.fromPoints(doc.indexToPosition(start), doc.indexToPosition(end)); + var range = Range.fromPoints(editor.indexToPosition(start), editor.indexToPosition(end)); editor.session.remove(range); range.end = range.start; //editor.selection.setRange(range); value = this.$updateTabstops(value); - snippetManager.insertSnippet(editor, value); + snippetManager.insertSnippet(editor, value) }, /** @@ -288,7 +293,7 @@ AceEmmetEditor.prototype = { lastZero = range.create(data.start, result); } - return result; + return result }, escape: function(ch) { if (ch == '$') return '\\$'; @@ -342,34 +347,28 @@ var keymap = { var editorProxy = new AceEmmetEditor(); exports.commands = new HashHandler(); exports.runEmmetCommand = function(editor) { - try { - editorProxy.setupContext(editor); - if (editorProxy.getSyntax() == "php") + editorProxy.setupContext(editor); + if (editorProxy.getSyntax() == "php") + return false; + var actions = emmet.require("actions"); + + if (this.action == "expand_abbreviation_with_tab") { + if (!editor.selection.isEmpty()) return false; - var actions = emmet.require("actions"); + } - if (this.action == "expand_abbreviation_with_tab") { - if (!editor.selection.isEmpty()) - return false; - } - - if (this.action == "wrap_with_abbreviation") { - // without setTimeout prompt doesn't work on firefox - return setTimeout(function() { - actions.run("wrap_with_abbreviation", editorProxy); - }, 0); - } - - var pos = editor.selection.lead; - var token = editor.session.getTokenAt(pos.row, pos.column); - if (token && /\btag\b/.test(token.type)) - return false; - + if (this.action == "wrap_with_abbreviation") { + // without setTimeout prompt doesn't work on firefox + return setTimeout(function() { + actions.run("wrap_with_abbreviation", editorProxy); + }, 0); + } + + try { var result = actions.run(this.action, editorProxy); } catch(e) { editor._signal("changeStatus", typeof e == "string" ? e : e.message); console.log(e); - result = false; } return result; }; @@ -384,35 +383,21 @@ for (var command in keymap) { }); } -exports.updateCommands = function(editor, enabled) { - if (enabled) { - editor.keyBinding.addKeyboardHandler(exports.commands); - } else { - editor.keyBinding.removeKeyboardHandler(exports.commands); - } -}; - -exports.isSupportedMode = function(modeId) { - return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs|handlebars/.test(modeId); -}; - var onChangeMode = function(e, target) { var editor = target; if (!editor) return; - var enabled = exports.isSupportedMode(editor.session.$modeId); + var modeId = editor.session.$modeId; + var enabled = modeId && /css|less|scss|sass|stylus|html|php/.test(modeId); if (e.enableEmmet === false) enabled = false; - if (enabled) { - if (typeof emmetPath == "string") { - require("ace/config").loadModule(emmetPath, function() { - emmetPath = null; - }); - } - } - exports.updateCommands(editor, enabled); + if (enabled) + editor.keyBinding.addKeyboardHandler(exports.commands); + else + editor.keyBinding.removeKeyboardHandler(exports.commands); }; + exports.AceEmmetEditor = AceEmmetEditor; require("ace/config").defineOptions(Editor.prototype, "editor", { enableEmmet: { @@ -424,11 +409,7 @@ require("ace/config").defineOptions(Editor.prototype, "editor", { } }); -exports.setCore = function(e) { - if (typeof e == "string") - emmetPath = e; - else - emmet = e; -}; + +exports.setCore = function(e) {emmet = e;}; }); diff --git a/lib/ace/ext/error_marker.js b/lib/ace/ext/error_marker.js deleted file mode 100644 index 5dbe3d2e..00000000 --- a/lib/ace/ext/error_marker.js +++ /dev/null @@ -1,214 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { -"use strict"; -var LineWidgets = require("../line_widgets").LineWidgets; -var dom = require("../lib/dom"); -var Range = require("../range").Range; - -function binarySearch(array, needle, comparator) { - var first = 0; - var last = array.length - 1; - - while (first <= last) { - var mid = (first + last) >> 1; - var c = comparator(needle, array[mid]); - if (c > 0) - first = mid + 1; - else if (c < 0) - last = mid - 1; - else - return mid; - } - - // Return the nearest lesser index, "-1" means "0, "-2" means "1", etc. - return -(first + 1); -} - -function findAnnotations(session, row, dir) { - var annotations = session.getAnnotations().sort(Range.comparePoints); - if (!annotations.length) - return; - - var i = binarySearch(annotations, {row: row, column: -1}, Range.comparePoints); - if (i < 0) - i = -i - 1; - - if (i >= annotations.length) - i = dir > 0 ? 0 : annotations.length - 1; - else if (i === 0 && dir < 0) - i = annotations.length - 1; - - var annotation = annotations[i]; - if (!annotation || !dir) - return; - - if (annotation.row === row) { - do { - annotation = annotations[i += dir]; - } while (annotation && annotation.row === row); - if (!annotation) - return annotations.slice(); - } - - - var matched = []; - row = annotation.row; - do { - matched[dir < 0 ? "unshift" : "push"](annotation); - annotation = annotations[i += dir]; - } while (annotation && annotation.row == row); - return matched.length && matched; -} - -exports.showErrorMarker = function(editor, dir) { - var session = editor.session; - if (!session.widgetManager) { - session.widgetManager = new LineWidgets(session); - session.widgetManager.attach(editor); - } - - var pos = editor.getCursorPosition(); - var row = pos.row; - var oldWidget = session.lineWidgets && session.lineWidgets[row]; - if (oldWidget) { - oldWidget.destroy(); - } else { - row -= dir; - } - var annotations = findAnnotations(session, row, dir); - var gutterAnno; - if (annotations) { - var annotation = annotations[0]; - pos.column = (annotation.pos && typeof annotation.column != "number" - ? annotation.pos.sc - : annotation.column) || 0; - pos.row = annotation.row; - gutterAnno = editor.renderer.$gutterLayer.$annotations[pos.row]; - } else if (oldWidget) { - return; - } else { - gutterAnno = { - text: ["Looks good!"], - className: "ace_ok" - }; - } - editor.session.unfold(pos.row); - editor.selection.moveToPosition(pos); - - var w = { - row: pos.row, - fixedWidth: true, - coverGutter: true, - el: dom.createElement("div") - }; - var el = w.el.appendChild(dom.createElement("div")); - var arrow = w.el.appendChild(dom.createElement("div")); - arrow.className = "error_widget_arrow " + gutterAnno.className; - - var left = editor.renderer.$cursorLayer - .getPixelPosition(pos).left; - arrow.style.left = left + editor.renderer.gutterWidth - 5 + "px"; - - w.el.className = "error_widget_wrapper"; - el.className = "error_widget " + gutterAnno.className; - el.innerHTML = gutterAnno.text.join("
    "); - - el.appendChild(dom.createElement("div")); - - var kb = function(_, hashId, keyString) { - if (hashId === 0 && (keyString === "esc" || keyString === "return")) { - w.destroy(); - return {command: "null"}; - } - }; - - w.destroy = function() { - if (editor.$mouseHandler.isMousePressed) - return; - editor.keyBinding.removeKeyboardHandler(kb); - session.widgetManager.removeLineWidget(w); - editor.off("changeSelection", w.destroy); - editor.off("changeSession", w.destroy); - editor.off("mouseup", w.destroy); - editor.off("change", w.destroy); - }; - - editor.keyBinding.addKeyboardHandler(kb); - editor.on("changeSelection", w.destroy); - editor.on("changeSession", w.destroy); - editor.on("mouseup", w.destroy); - editor.on("change", w.destroy); - - editor.session.widgetManager.addLineWidget(w); - - w.el.onmousedown = editor.focus.bind(editor); - - editor.renderer.scrollCursorIntoView(null, 0.5, {bottom: w.el.offsetHeight}); -}; - - -dom.importCssString("\ - .error_widget_wrapper {\ - background: inherit;\ - color: inherit;\ - border:none\ - }\ - .error_widget {\ - border-top: solid 2px;\ - border-bottom: solid 2px;\ - margin: 5px 0;\ - padding: 10px 40px;\ - white-space: pre-wrap;\ - }\ - .error_widget.ace_error, .error_widget_arrow.ace_error{\ - border-color: #ff5a5a\ - }\ - .error_widget.ace_warning, .error_widget_arrow.ace_warning{\ - border-color: #F1D817\ - }\ - .error_widget.ace_info, .error_widget_arrow.ace_info{\ - border-color: #5a5a5a\ - }\ - .error_widget.ace_ok, .error_widget_arrow.ace_ok{\ - border-color: #5aaa5a\ - }\ - .error_widget_arrow {\ - position: absolute;\ - border: solid 5px;\ - border-top-color: transparent!important;\ - border-right-color: transparent!important;\ - border-left-color: transparent!important;\ - top: -5px;\ - }\ -", ""); - -}); \ No newline at end of file diff --git a/lib/ace/ext/language_tools.js b/lib/ace/ext/language_tools.js index 563fe58a..e5cd8bb4 100644 --- a/lib/ace/ext/language_tools.js +++ b/lib/ace/ext/language_tools.js @@ -34,15 +34,10 @@ define(function(require, exports, module) { var snippetManager = require("../snippets").snippetManager; var Autocomplete = require("../autocomplete").Autocomplete; var config = require("../config"); -var lang = require("../lib/lang"); -var util = require("../autocomplete/util"); var textCompleter = require("../autocomplete/text_completer"); var keyWordCompleter = { getCompletions: function(editor, session, pos, prefix, callback) { - if (session.$mode.completer) { - return session.$mode.completer.getCompletions(editor, session, pos, prefix, callback); - } var state = editor.session.getState(pos.row); var completions = session.$mode.getCompletions(state, session, pos, prefix); callback(null, completions); @@ -51,9 +46,10 @@ var keyWordCompleter = { var snippetCompleter = { getCompletions: function(editor, session, pos, prefix, callback) { + var scope = snippetManager.$getScope(editor); var snippetMap = snippetManager.snippetMap; var completions = []; - snippetManager.getActiveScopes(editor).forEach(function(scope) { + [scope, "_"].forEach(function(scope) { var snippets = snippetMap[scope] || []; for (var i = snippets.length; i--;) { var s = snippets[i]; @@ -63,117 +59,42 @@ var snippetCompleter = { completions.push({ caption: caption, snippet: s.content, - meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet", - type: "snippet" + meta: s.tabTrigger && !s.name ? s.tabTrigger + "\u21E5 " : "snippet" }); } }, this); callback(null, completions); - }, - getDocTooltip: function(item) { - if (item.type == "snippet" && !item.docHTML) { - item.docHTML = [ - "", lang.escapeHTML(item.caption), "", "
    ", - lang.escapeHTML(item.snippet) - ].join(""); - } } }; var completers = [snippetCompleter, textCompleter, keyWordCompleter]; -// Allows default completers to be removed or replaced with a explict set of completers -// A null argument here will result in an empty completer array, not a null attribute -exports.setCompleters = function(val) { - completers = val || []; -}; exports.addCompleter = function(completer) { completers.push(completer); }; -// Exports existing completer so that user can construct his own set of completers. -exports.textCompleter = textCompleter; -exports.keyWordCompleter = keyWordCompleter; -exports.snippetCompleter = snippetCompleter; - var expandSnippet = { name: "expandSnippet", exec: function(editor) { - return snippetManager.expandWithTab(editor); + var success = snippetManager.expandWithTab(editor); + if (!success) + editor.execCommand("indent"); }, - bindKey: "Tab" -}; - -var onChangeMode = function(e, editor) { - loadSnippetsForMode(editor.session.$mode); -}; - -var loadSnippetsForMode = function(mode) { - var id = mode.$id; - if (!snippetManager.files) - snippetManager.files = {}; - loadSnippetFile(id); - if (mode.modes) - mode.modes.forEach(loadSnippetsForMode); -}; - -var loadSnippetFile = function(id) { - if (!id || snippetManager.files[id]) - return; - var snippetFilePath = id.replace("mode", "snippets"); - snippetManager.files[id] = {}; - config.loadModule(snippetFilePath, function(m) { - if (m) { - snippetManager.files[id] = m; - if (!m.snippets && m.snippetText) - m.snippets = snippetManager.parseSnippetFile(m.snippetText); - snippetManager.register(m.snippets || [], m.scope); - if (m.includeScopes) { - snippetManager.snippetMap[m.scope].includeScopes = m.includeScopes; - m.includeScopes.forEach(function(x) { - loadSnippetFile("ace/mode/" + x); - }); - } - } - }); -}; - -function getCompletionPrefix(editor) { - var pos = editor.getCursorPosition(); - var line = editor.session.getLine(pos.row); - var prefix; - // Try to find custom prefixes on the completers - editor.completers.forEach(function(completer) { - if (completer.identifierRegexps) { - completer.identifierRegexps.forEach(function(identifierRegex) { - if (!prefix && identifierRegex) - prefix = util.retrievePrecedingIdentifier(line, pos.column, identifierRegex); - }); - } - }); - return prefix || util.retrievePrecedingIdentifier(line, pos.column); + bindKey: "tab" } -var doLiveAutocomplete = function(e) { - var editor = e.editor; - 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)) - editor.completer.detach(); - } - else if (e.command.name === "insertstring") { - var prefix = getCompletionPrefix(editor); - // Only autocomplete if there's a prefix that can be matched - if (prefix && !hasCompleter) { - if (!editor.completer) { - // Create new autocompleter - editor.completer = new Autocomplete(); +var onChangeMode = function(e, editor) { + var mode = editor.session.$mode; + var id = mode.$id + if (!snippetManager.files) snippetManager.files = {}; + if (id && !snippetManager.files[id]) { + var snippetFilePath = id.replace("mode", "snippets"); + config.loadModule(snippetFilePath, function(m) { + if (m) { + snippetManager.files[id] = m; + m.snippets = snippetManager.parseSnippetFile(m.snippetText); + snippetManager.register(m.snippets, m.scope); } - // Disable autoInsert - editor.completer.autoInsert = false; - editor.completer.showPopup(editor); - } + }); } }; @@ -182,8 +103,7 @@ require("../config").defineOptions(Editor.prototype, "editor", { enableBasicAutocompletion: { set: function(val) { if (val) { - if (!this.completers) - this.completers = Array.isArray(val)? val: completers; + this.completers = completers this.commands.addCommand(Autocomplete.startCommand); } else { this.commands.removeCommand(Autocomplete.startCommand); @@ -191,29 +111,12 @@ require("../config").defineOptions(Editor.prototype, "editor", { }, value: false }, - /** - * Enable live autocomplete. If the value is an array, it is assumed to be an array of completers - * and will use them instead of the default completers. - */ - enableLiveAutocompletion: { - set: function(val) { - if (val) { - if (!this.completers) - this.completers = Array.isArray(val)? val: completers; - // On each change automatically trigger the autocomplete - this.commands.on('afterExec', doLiveAutocomplete); - } else { - this.commands.removeListener('afterExec', doLiveAutocomplete); - } - }, - value: false - }, enableSnippets: { set: function(val) { if (val) { this.commands.addCommand(expandSnippet); this.on("changeMode", onChangeMode); - onChangeMode(null, this); + onChangeMode(null, this) } else { this.commands.removeCommand(expandSnippet); this.off("changeMode", onChangeMode); @@ -222,4 +125,5 @@ require("../config").defineOptions(Editor.prototype, "editor", { value: false } }); -}); + +}); \ No newline at end of file diff --git a/lib/ace/ext/linking.js b/lib/ace/ext/linking.js deleted file mode 100644 index cfd333b2..00000000 --- a/lib/ace/ext/linking.js +++ /dev/null @@ -1,78 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -var Editor = require("ace/editor").Editor; - -require("../config").defineOptions(Editor.prototype, "editor", { - enableLinking: { - set: function(val) { - if (val) { - this.on("click", onClick); - this.on("mousemove", onMouseMove); - } else { - this.off("click", onClick); - this.off("mousemove", onMouseMove); - } - }, - value: false - } -}) - -function onMouseMove(e) { - var editor = e.editor; - var ctrl = e.getAccelKey(); - - if (ctrl) { - var editor = e.editor; - var docPos = e.getDocumentPosition(); - var session = editor.session; - var token = session.getTokenAt(docPos.row, docPos.column); - - editor._emit("linkHover", {position: docPos, token: token}); - } -} - -function onClick(e) { - var ctrl = e.getAccelKey(); - var button = e.getButton(); - - if (button == 0 && ctrl) { - var editor = e.editor; - var docPos = e.getDocumentPosition(); - var session = editor.session; - var token = session.getTokenAt(docPos.row, docPos.column); - - editor._emit("linkClick", {position: docPos, token: token}); - } -} - -}); diff --git a/lib/ace/ext/menu_tools/add_editor_menu_options.js b/lib/ace/ext/menu_tools/add_editor_menu_options.js index eb90e31d..fd56859b 100644 --- a/lib/ace/ext/menu_tools/add_editor_menu_options.js +++ b/lib/ace/ext/menu_tools/add_editor_menu_options.js @@ -60,50 +60,44 @@ module.exports.addEditorMenuOptions = function addEditorMenuOptions (editor) { var modelist = require('../modelist'); var themelist = require('../themelist'); editor.menuOptions = { - setNewLineMode: [{ - textContent: "unix", - value: "unix" + "setNewLineMode" : [{ + "textContent" : "unix", + "value" : "unix" }, { - textContent: "windows", - value: "windows" + "textContent" : "windows", + "value" : "windows" }, { - textContent: "auto", - value: "auto" + "textContent" : "auto", + "value" : "auto" }], - setTheme: [], - setMode: [], - setKeyboardHandler: [{ - textContent: "ace", - value: "" + "setTheme" : [], + "setMode" : [], + "setKeyboardHandler": [{ + "textContent" : "ace", + "value" : "" }, { - textContent: "vim", - value: "ace/keyboard/vim" + "textContent" : "vim", + "value" : "ace/keyboard/vim" }, { - textContent: "emacs", - value: "ace/keyboard/emacs" - }, { - textContent: "textarea", - value: "ace/keyboard/textarea" - }, { - textContent: "sublime", - value: "ace/keyboard/sublime" + "textContent" : "emacs", + "value" : "ace/keyboard/emacs" }] }; editor.menuOptions.setTheme = themelist.themes.map(function(theme) { return { - textContent: theme.caption, - value: theme.theme + 'textContent' : theme.desc, + 'value' : theme.theme }; }); editor.menuOptions.setMode = modelist.modes.map(function(mode) { return { - textContent: mode.name, - value: mode.mode + 'textContent' : mode.name, + 'value' : mode.mode }; }); }; -}); +}); \ No newline at end of file diff --git a/lib/ace/ext/menu_tools/generate_settings_menu.js b/lib/ace/ext/menu_tools/generate_settings_menu.js index 2ee1ae09..16d3a76c 100644 --- a/lib/ace/ext/menu_tools/generate_settings_menu.js +++ b/lib/ace/ext/menu_tools/generate_settings_menu.js @@ -91,12 +91,6 @@ module.exports.generateSettingsMenu = function generateSettingsMenu (editor) { elements.forEach(function(element) { topmenu.appendChild(element); }); - - var el = topmenu.appendChild(document.createElement('div')); - var version = "1.1.9"; - el.style.padding = "1em"; - el.textContent = "Ace version " + version; - return topmenu; } /** diff --git a/lib/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js b/lib/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js index 99e006b0..e62d931a 100644 --- a/lib/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js +++ b/lib/ace/ext/menu_tools/get_editor_keyboard_shortcuts.js @@ -67,22 +67,31 @@ module.exports.getEditorKeybordShortcuts = function(editor) { var keybindings = []; var commandMap = {}; editor.keyBinding.$handlers.forEach(function(handler) { - var ckb = handler.commandKeyBinding; + var ckb = handler.commmandKeyBinding; for (var i in ckb) { - var key = i.replace(/(^|-)\w/g, function(x) { return x.toUpperCase(); }); - var commands = ckb[i]; - if (!Array.isArray(commands)) - commands = [commands]; - commands.forEach(function(command) { + var modifier = parseInt(i); + if (modifier == -1) { + modifier = ""; + } else if(isNaN(modifier)) { + modifier = i; + } else { + modifier = "" + + (modifier & KEY_MODS.command ? "Cmd-" : "") + + (modifier & KEY_MODS.ctrl ? "Ctrl-" : "") + + (modifier & KEY_MODS.alt ? "Alt-" : "") + + (modifier & KEY_MODS.shift ? "Shift-" : ""); + } + for (var key in ckb[i]) { + var command = ckb[i][key] if (typeof command != "string") command = command.name if (commandMap[command]) { - commandMap[command].key += "|" + key; + commandMap[command].key += "|" + modifier + key; } else { - commandMap[command] = {key: key, command: command}; + commandMap[command] = {key: modifier+key, command: command}; keybindings.push(commandMap[command]); - } - }); + } + } } }); return keybindings; diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 675a4b85..b785cd46 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -43,20 +43,17 @@ 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|adoc"], + ActionScript:["as"], + AsciiDoc: ["asciidoc"], Assembly_x86:["asm"], AutoHotKey: ["ahk"], BatchFile: ["bat|cmd"], C9Search: ["c9search_results"], - C_Cpp: ["cpp|c|cc|cxx|h|hh|hpp"], - Cirru: ["cirru|cr"], - Clojure: ["clj|cljs"], - Cobol: ["CBL|COB"], - coffee: ["coffee|cf|cson|^Cakefile"], + C_Cpp: ["c|cc|cpp|cxx|h|hh|hpp"], + Clojure: ["clj"], + Cobol: ["^CBL|COB"], + coffee: ["^Cakefile|coffee|cf|cson"], ColdFusion: ["cfm"], CSharp: ["cs"], CSS: ["css"], @@ -64,42 +61,29 @@ var supportedModes = { D: ["d|di"], Dart: ["dart"], Diff: ["diff|patch"], - Dockerfile: ["^Dockerfile"], Dot: ["dot"], - Dummy: ["dummy"], - DummySyntax: ["dummy"], - Eiffel: ["e"], - EJS: ["ejs"], - Elixir: ["ex|exs"], - Elm: ["elm"], Erlang: ["erl|hrl"], + EJS: ["ejs"], Forth: ["frt|fs|ldr"], FTL: ["ftl"], - Gcode: ["gcode"], - Gherkin: ["feature"], - Gitignore: ["^.gitignore"], Glsl: ["glsl|frag|vert"], golang: ["go"], Groovy: ["groovy"], HAML: ["haml"], - Handlebars: ["hbs|handlebars|tpl|mustache"], Haskell: ["hs"], haXe: ["hx"], - HTML: ["html|htm|xhtml"], + HTML: ["htm|html|xhtml"], HTML_Ruby: ["erb|rhtml|html.erb"], - INI: ["ini|conf|cfg|prefs"], - Io: ["io"], - Jack: ["jack"], + Ini: ["Ini|conf"], Jade: ["jade"], Java: ["java"], - JavaScript: ["js|jsm"], + JavaScript: ["js"], JSON: ["json"], JSONiq: ["jq"], JSP: ["jsp"], JSX: ["jsx"], Julia: ["jl"], - LaTeX: ["tex|latex|ltx|bib"], - Lean: ["lean|hlean"], + LaTeX: ["latex|tex|ltx|bib"], LESS: ["less"], Liquid: ["liquid"], Lisp: ["lisp"], @@ -109,23 +93,19 @@ var supportedModes = { Lua: ["lua"], LuaPage: ["lp"], Lucene: ["lucene"], - Makefile: ["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"], - Markdown: ["md|markdown"], - Mask: ["mask"], + Makefile: ["^GNUmakefile|^makefile|^Makefile|^OCamlMakefile|make"], MATLAB: ["matlab"], - MEL: ["mel"], - MUSHCode: ["mc|mush"], + Markdown: ["md|markdown"], MySQL: ["mysql"], + MUSHCode: ["mc|mush"], Nix: ["nix"], - Nim: ["nim"], ObjectiveC: ["m|mm"], OCaml: ["ml|mli"], Pascal: ["pas|p"], Perl: ["pl|pm"], pgSQL: ["pgsql"], - PHP: ["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp"], + PHP: ["php|phtml"], Powershell: ["ps1"], - Praat: ["praat|praatscript|psc|proc"], Prolog: ["plg|prolog"], Properties: ["properties"], Protobuf: ["proto"], @@ -133,21 +113,17 @@ var supportedModes = { R: ["r"], RDoc: ["Rd"], RHTML: ["Rhtml"], - Ruby: ["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"], + Ruby: ["ru|gemspec|rake|rb"], Rust: ["rs"], SASS: ["sass"], SCAD: ["scad"], Scala: ["scala"], Scheme: ["scm|rkt"], SCSS: ["scss"], - SH: ["sh|bash|^.bashrc"], - SJS: ["sjs"], - Smarty: ["smarty|tpl"], - snippets: ["snippets"], - Soy_Template:["soy"], + SH: ["sh|bash"], Space: ["space"], + snippets: ["snippets"], SQL: ["sql"], - SQLServer: ["sqlserver"], Stylus: ["styl|stylus"], SVG: ["svg"], Tcl: ["tcl"], @@ -156,24 +132,19 @@ var supportedModes = { Textile: ["textile"], Toml: ["toml"], Twig: ["twig"], - Typescript: ["ts|typescript|str"], - Vala: ["vala"], - VBScript: ["vbs|vb"], + Typescript: ["typescript|ts|str"], + VBScript: ["vbs"], Velocity: ["vm"], - Verilog: ["v|vh|sv|svh"], - VHDL: ["vhd|vhdl"], - XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"], + XML: ["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"], XQuery: ["xq"], - YAML: ["yaml|yml"], - // Add the missing mode "Django" to ext-modelist - Django: ["html"] + YAML: ["yaml"] }; var nameOverrides = { ObjectiveC: "Objective-C", CSharp: "C#", golang: "Go", - C_Cpp: "C and C++", + C_Cpp: "C/C++", coffee: "CoffeeScript", HTML_Ruby: "HTML (Ruby)", FTL: "FreeMarker" @@ -181,7 +152,7 @@ var nameOverrides = { var modesByName = {}; for (var name in supportedModes) { var data = supportedModes[name]; - var displayName = (nameOverrides[name] || name).replace(/_/g, " "); + var displayName = nameOverrides[name] || name; var filename = name.toLowerCase(); var mode = new Mode(filename, displayName, data[0]); modesByName[filename] = mode; @@ -195,3 +166,4 @@ module.exports = { }; }); + diff --git a/lib/ace/ext/old_ie.js b/lib/ace/ext/old_ie.js index 8b8ce977..ca67888f 100644 --- a/lib/ace/ext/old_ie.js +++ b/lib/ace/ext/old_ie.js @@ -103,12 +103,6 @@ patch( }" ); -patch( - require("../mode/text").Mode.prototype, "getTokenizer", - /Tokenizer/, - "TokenizerModule.Tokenizer" -); - useragent.isOldIE = true; }); diff --git a/lib/ace/ext/searchbox.css b/lib/ace/ext/searchbox.css index 5de8d847..c0f5f284 100644 --- a/lib/ace/ext/searchbox.css +++ b/lib/ace/ext/searchbox.css @@ -7,7 +7,7 @@ background-color: #ddd; border: 1px solid #cbcbcb; border-top: 0 none; - max-width: 325px; + max-width: 297px; overflow: hidden; margin: 0; padding: 4px; @@ -16,7 +16,6 @@ position: absolute; top: 0px; z-index: 99; - white-space: normal; } .ace_search.left { border-left: 0 none; @@ -47,6 +46,7 @@ -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; + display: block; float: left; height: 22px; outline: 0; @@ -60,6 +60,7 @@ border: 0 none; border-left: 1px solid #dcdcdc; cursor: pointer; + display: block; float: left; height: 22px; margin: 0; @@ -92,9 +93,12 @@ border: 0 none; color: #656565; cursor: pointer; + display: block; float: right; - font: 16px/16px Arial; + font-family: Arial; + font-size: 16px; height: 14px; + line-height: 16px; margin: 5px 1px 9px 5px; padding: 0; text-align: center; diff --git a/lib/ace/ext/searchbox.js b/lib/ace/ext/searchbox.js index b316aa75..fbbaa8f3 100644 --- a/lib/ace/ext/searchbox.js +++ b/lib/ace/ext/searchbox.js @@ -46,7 +46,6 @@ var html = '\
    \ \ @@ -171,11 +170,6 @@ var SearchBox = function(editor, range, showReplaceForm) { sb.replace(); sb.findPrev(); }, - "Alt-Return": function(sb) { - if (sb.activeInput == sb.replaceInput) - sb.replaceAll(); - sb.findAll(); - }, "Tab": function(sb) { (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); } @@ -235,18 +229,6 @@ var SearchBox = function(editor, range, showReplaceForm) { this.findPrev = function() { this.find(true, true); }; - this.findAll = function(){ - var range = this.editor.findAll(this.searchInput.value, { - regExp: this.regExpOption.checked, - caseSensitive: this.caseSensitiveOption.checked, - wholeWord: this.wholeWordOption.checked - }); - var noMatch = !range && this.searchInput.value; - dom.setCssClass(this.searchBox, "ace_nomatch", noMatch); - this.editor._emit("findSearchBox", { match: !noMatch }); - this.highlight(); - this.hide(); - }; this.replace = function() { if (!this.editor.getReadOnly()) this.editor.replace(this.replaceInput.value); @@ -281,10 +263,6 @@ var SearchBox = function(editor, range, showReplaceForm) { this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb); }; - this.isFocused = function() { - var el = document.activeElement; - return el == this.searchInput || el == this.replaceInput; - } }).call(SearchBox.prototype); exports.SearchBox = SearchBox; diff --git a/lib/ace/ext/spellcheck.js b/lib/ace/ext/spellcheck.js index 08bf2189..af596a49 100644 --- a/lib/ace/ext/spellcheck.js +++ b/lib/ace/ext/spellcheck.js @@ -17,9 +17,8 @@ exports.contextMenuHandler = function(e){ var PLACEHOLDER = "\x01\x01"; var value = w + " " + PLACEHOLDER; text.value = value; - text.setSelectionRange(w.length, w.length + 1); + text.setSelectionRange(w.length + 1, w.length + 1); text.setSelectionRange(0, 0); - text.setSelectionRange(0, w.length); var afterKeydown = false; event.addListener(text, "keydown", function onKeydown() { diff --git a/lib/ace/ext/static.css b/lib/ace/ext/static.css index 51986c3f..bd479780 100644 --- a/lib/ace/ext/static.css +++ b/lib/ace/ext/static.css @@ -1,38 +1,23 @@ .ace_static_highlight { - font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace; - font-size: 12px; - white-space: pre-wrap + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', 'Droid Sans Mono', monospace; + font-size: 12px; } .ace_static_highlight .ace_gutter { - width: 2em; + width: 25px !important; + display: block; + float: left; text-align: right; padding: 0 3px 0 0; margin-right: 3px; + position: static !important; } -.ace_static_highlight.ace_show_gutter .ace_line { - padding-left: 2.6em; -} - -.ace_static_highlight .ace_line { position: relative; } +.ace_static_highlight .ace_line { clear: both; } .ace_static_highlight .ace_gutter-cell { - -moz-user-select: -moz-none; - -khtml-user-select: none; - -webkit-user-select: none; - user-select: none; - top: 0; - bottom: 0; - left: 0; - position: absolute; -} - - -.ace_static_highlight .ace_gutter-cell:before { - content: counter(ace_line, decimal); - counter-increment: ace_line; -} -.ace_static_highlight { - counter-reset: ace_line; -} + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + user-select: none; +} \ No newline at end of file diff --git a/lib/ace/ext/static_highlight.js b/lib/ace/ext/static_highlight.js index 2acb3ac5..2729bf04 100644 --- a/lib/ace/ext/static_highlight.js +++ b/lib/ace/ext/static_highlight.js @@ -35,54 +35,6 @@ var EditSession = require("../edit_session").EditSession; var TextLayer = require("../layer/text").Text; 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+)/); - var mode = opts.mode || m && ("ace/mode/" + m[1]); - if (!mode) - return false; - var theme = opts.theme || "ace/theme/textmate"; - - var data = ""; - var nodes = []; - - if (el.firstElementChild) { - var textLen = 0; - for (var i = 0; i < el.childNodes.length; i++) { - var ch = el.childNodes[i]; - if (ch.nodeType == 3) { - textLen += ch.data.length; - data += ch.data; - } else { - nodes.push(textLen, ch); - } - } - } else { - data = dom.getInnerText(el); - if (opts.trim) - data = data.trim(); - } - - highlight.render(data, mode, theme, opts.firstLineNumber, !opts.showGutter, function (highlighted) { - dom.importCssString(highlighted.css, "ace_highlight"); - el.innerHTML = highlighted.html; - var container = el.firstChild.firstChild; - for (var i = 0; i < nodes.length; i += 2) { - var pos = highlighted.session.doc.indexToPosition(nodes[i]); - var node = nodes[i + 1]; - var lineEl = container.children[pos.row]; - lineEl && lineEl.appendChild(node); - } - callback && callback(); - }); -}; - /** * Transforms a given input code snippet into HTML using the given mode * @@ -102,8 +54,9 @@ var highlight = function(el, opts, callback) { * and `css`. * @returns {object} An object containing the properties `html` and `css`. */ -highlight.render = function(input, mode, theme, lineStart, disableGutter, callback) { - var waiting = 1; + +exports.render = function(input, mode, theme, lineStart, disableGutter, callback) { + var waiting = 0; var modeCache = EditSession.prototype.$modes; // if either the theme or the mode were specified as objects @@ -115,17 +68,11 @@ highlight.render = function(input, mode, theme, lineStart, disableGutter, callba --waiting || done(); }); } - // allow setting mode options e.h {path: "ace/mode/php", inline:true} - var modeOptions; - if (mode && typeof mode === "object" && !mode.getTokenizer) { - modeOptions = mode; - mode = modeOptions.path; - } + if (typeof mode == "string") { waiting++; config.loadModule(['mode', mode], function(m) { - if (!modeCache[mode] || modeOptions) - modeCache[mode] = new m.Mode(modeOptions); + if (!modeCache[mode]) modeCache[mode] = new m.Mode(); mode = modeCache[mode]; --waiting || done(); }); @@ -133,28 +80,33 @@ highlight.render = function(input, mode, theme, lineStart, disableGutter, callba // loads or passes the specified mode module then calls renderer function done() { - var result = highlight.renderSync(input, mode, theme, lineStart, disableGutter); + var result = exports.renderSync(input, mode, theme, lineStart, disableGutter); return callback ? callback(result) : result; } - return --waiting || done(); + return waiting || done(); }; -/** - * Transforms a given input code snippet into HTML using the given mode - * @param {string} input Code snippet - * @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode') - * @param {string} r Code snippet - * @returns {object} An object containing: html, css - */ -highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { +/* Transforms a given input code snippet into HTML using the given mode +* +* @param {string} input Code snippet +* @param {mode} mode Mode loaded from /ace/mode (use 'ServerSideHiglighter.getMode') +* @param {string} r Code snippet +* @returns {object} An object containing: html, css +*/ + +exports.renderSync = function(input, mode, theme, lineStart, disableGutter) { lineStart = parseInt(lineStart || 1, 10); var session = new EditSession(""); session.setUseWorker(false); session.setMode(mode); - var textLayer = new SimpleTextLayer(); + var textLayer = new TextLayer(document.createElement("div")); textLayer.setSession(session); + textLayer.config = { + characterWidth: 10, + lineHeight: 20 + }; session.setValue(input); @@ -164,15 +116,14 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { for(var ix = 0; ix < length; ix++) { stringBuilder.push("
    "); if (!disableGutter) - stringBuilder.push("" + /*(ix + lineStart) + */ ""); + stringBuilder.push("" + (ix + lineStart) + ""); textLayer.$renderLine(stringBuilder, ix, true, false); - stringBuilder.push("\n
    "); + stringBuilder.push("
    "); } // let's prepare the whole html var html = "
    " + - "
    " + + "
    " + stringBuilder.join("") + "
    " + "
    "; @@ -181,11 +132,8 @@ highlight.renderSync = function(input, mode, theme, lineStart, disableGutter) { return { css: baseStyles + theme.cssText, - html: html, - session: session + html: html }; }; -module.exports = highlight; -module.exports.highlight =highlight; }); diff --git a/lib/ace/ext/static_highlight_test.js b/lib/ace/ext/static_highlight_test.js index 6271666d..bdbecbfc 100644 --- a/lib/ace/ext/static_highlight_test.js +++ b/lib/ace/ext/static_highlight_test.js @@ -28,14 +28,7 @@ module.exports = { var mode = new JavaScriptMode(); var result = highlighter.render(snippet, mode, theme); - assert.equal(result.html, "
    " - + "
    /** this is a function\n
    " - + "
    *\n
    " - + "
    */\n
    " - + "
    function hello (a, b, c) {\n
    " - + "
    console.log(a * b + c + 'sup$');\n
    " - + "
    }\n
    " - + "
    "); + assert.equal(result.html, "
    1/**\xa0this\xa0is\xa0a\xa0function
    2*
    3*/
    4function\xa0hello\xa0(a,\xa0b,\xa0c)\xa0{
    5\xa0\xa0\xa0\xa0console.log(a\xa0*\xa0b\xa0+\xa0c\xa0+\xa0'sup$');
    6}
    "); assert.ok(!!result.css); next(); }, diff --git a/lib/ace/ext/statusbar.js b/lib/ace/ext/statusbar.js index 5e5b0572..666febfa 100644 --- a/lib/ace/ext/statusbar.js +++ b/lib/ace/ext/statusbar.js @@ -28,8 +28,9 @@ var StatusBar = function(editor, parentNode) { str && status.push(str, separator || "|"); } - add(editor.keyBinding.getStatusText(editor)); - if (editor.commands.recording) + if (editor.$vimModeHandler) + add(editor.$vimModeHandler.getStatusText()); + else if (editor.commands.recording) add("REC"); var c = editor.selection.lead; diff --git a/lib/ace/ext/textarea.js b/lib/ace/ext/textarea.js index c9972488..fee9b9b2 100644 --- a/lib/ace/ext/textarea.js +++ b/lib/ace/ext/textarea.js @@ -74,7 +74,7 @@ function applyStyles(elm, styles) { function setupContainer(element, getValue) { if (element.type != 'textarea') { - throw new Error("Textarea required!"); + throw "Textarea required!"; } var parentNode = element.parentNode; @@ -155,7 +155,7 @@ function setupContainer(element, getValue) { return container; } -exports.transformTextarea = function(element, options) { +exports.transformTextarea = function(element, loader) { var session; var container = setupContainer(element, function() { return session.getValue(); @@ -215,8 +215,9 @@ exports.transformTextarea = function(element, options) { applyStyles(settingDiv, settingDivStyles); container.appendChild(settingDiv); - options = options || exports.defaultOptions; // Power up ace on the textarea: + var options = {}; + var editor = ace.edit(editorDiv); session = editor.getSession(); @@ -227,10 +228,10 @@ exports.transformTextarea = function(element, options) { container.appendChild(settingOpener); // Create the API. - setupApi(editor, editorDiv, settingDiv, ace, options, load); + setupApi(editor, editorDiv, settingDiv, ace, options, loader); // Create the setting's panel. - setupSettingPanel(settingDiv, settingOpener, editor); + setupSettingPanel(settingDiv, settingOpener, editor, options); var state = ""; event.addListener(settingOpener, "mousemove", function(e) { @@ -295,15 +296,37 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) { }; editor.$setOption = editor.setOption; - editor.$getOption = editor.getOption; editor.setOption = function(key, value) { + if (options[key] == value) return; + switch (key) { case "mode": - editor.$setOption("mode", "ace/mode/" + value) + if (value != "text") { + // Load the required mode file. Files get loaded only once. + loader("mode-" + value + ".js", "ace/mode/" + value, function() { + var aceMode = require("../mode/" + value).Mode; + session.setMode(new aceMode()); + }); + } else { + session.setMode(new (require("../mode/text").Mode)); + } break; + case "theme": - editor.$setOption("theme", "ace/theme/" + value) + if (value != "textmate") { + // Load the required theme file. Files get loaded only once. + loader("theme-" + value + ".js", "ace/theme/" + value, function() { + editor.setTheme("ace/theme/" + value); + }); + } else { + editor.setTheme("ace/theme/textmate"); + } break; + + case "fontSize": + editorDiv.style.fontSize = value; + break; + case "keybindings": switch (value) { case "vim": @@ -318,55 +341,58 @@ function setupApi(editor, editorDiv, settingDiv, ace, options, loader) { break; case "softWrap": - case "fontSize": - editor.$setOption(key, value); + switch (value) { + case "off": + session.setUseWrapMode(false); + renderer.setPrintMarginColumn(80); + break; + case "40": + session.setUseWrapMode(true); + session.setWrapLimitRange(40, 40); + renderer.setPrintMarginColumn(40); + break; + case "80": + session.setUseWrapMode(true); + session.setWrapLimitRange(80, 80); + renderer.setPrintMarginColumn(80); + break; + case "free": + session.setUseWrapMode(true); + session.setWrapLimitRange(null, null); + renderer.setPrintMarginColumn(80); + break; + } break; default: editor.$setOption(key, toBool(value)); } + + options[key] = value; }; editor.getOption = function(key) { - switch (key) { - case "mode": - return editor.$getOption("mode").substr("ace/mode/".length) - break; - - case "theme": - return editor.$getOption("theme").substr("ace/theme/".length) - break; - - case "keybindings": - var value = editor.getKeyboardHandler() - switch (value && value.$id) { - case "ace/keyboard/vim": - return "vim"; - case "ace/keyboard/emacs": - return "emacs"; - default: - return "ace"; - } - break; - - default: - return editor.$getOption(key); - } + return options[key]; }; - editor.setOptions(options); + editor.getOptions = function() { + return options; + }; + + editor.setOptions(exports.options); + return editor; } -function setupSettingPanel(settingDiv, settingOpener, editor) { +function setupSettingPanel(settingDiv, settingOpener, editor, options) { var BOOL = null; var desc = { mode: "Mode:", - wrap: "Soft Wrap:", + gutter: "Display Gutter:", theme: "Theme:", fontSize: "Font Size:", - showGutter: "Display Gutter:", + softWrap: "Soft Wrap:", keybindings: "Keyboard", showPrintMargin: "Show Print Margin:", useSoftTabs: "Use Soft Tabs:", @@ -419,7 +445,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor) { twilight: "Twilight", vibrant_ink: "Vibrant Ink" }, - showGutter: BOOL, + gutter: BOOL, fontSize: { "10px": "10px", "11px": "11px", @@ -427,7 +453,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor) { "14px": "14px", "16px": "16px" }, - wrap: { + softWrap: { off: "Off", 40: "40", 80: "80", @@ -450,7 +476,7 @@ function setupSettingPanel(settingDiv, settingOpener, editor) { if (!obj) { builder.push( "" ); return; @@ -470,10 +496,10 @@ function setupSettingPanel(settingDiv, settingOpener, editor) { builder.push(""); } - for (var option in exports.defaultOptions) { + for (var option in options) { table.push("", desc[option], ""); table.push(""); - renderOption(table, option, optionValues[option], editor.getOption(option)); + renderOption(table, option, optionValues[option], options[option]); table.push(""); } table.push(""); @@ -506,12 +532,12 @@ function setupSettingPanel(settingDiv, settingOpener, editor) { } // Default startup options. -exports.defaultOptions = { - mode: "javascript", +exports.options = { + mode: "text", theme: "textmate", - wrap: "off", + gutter: "false", fontSize: "12px", - showGutter: "false", + softWrap: "off", keybindings: "ace", showPrintMargin: "false", useSoftTabs: "true", diff --git a/lib/ace/ext/themelist.js b/lib/ace/ext/themelist.js index 0df76b02..1032f72c 100644 --- a/lib/ace/ext/themelist.js +++ b/lib/ace/ext/themelist.js @@ -30,6 +30,8 @@ * * ***** END LICENSE BLOCK ***** */ +/*jslint indent: 4, maxerr: 50, white: true, browser: true, vars: true*/ +/*global define, require */ /** * Generates a list of themes available when ace was built. @@ -41,62 +43,36 @@ define(function(require, exports, module) { "use strict"; -require("ace/lib/fixoldbrowsers"); - -var themeData = [ - ["Chrome" ], - ["Clouds" ], - ["Crimson Editor" ], - ["Dawn" ], - ["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"], - ["Cobalt" ,"cobalt" , "dark"], - ["idle Fingers" ,"idle_fingers" , "dark"], - ["krTheme" ,"kr_theme" , "dark"], - ["Merbivore" ,"merbivore" , "dark"], - ["Merbivore Soft" ,"merbivore_soft" , "dark"], - ["Mono Industrial" ,"mono_industrial" , "dark"], - ["Monokai" ,"monokai" , "dark"], - ["Pastel on dark" ,"pastel_on_dark" , "dark"], - ["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"], - ["Twilight" ,"twilight" , "dark"], - ["Vibrant Ink" ,"vibrant_ink" , "dark"] -]; - - -exports.themesByName = {}; /** * An array containing information about available themes. */ -exports.themes = themeData.map(function(data) { - var name = data[1] || data[0].replace(/ /g, "_").toLowerCase(); - var theme = { - caption: data[0], - theme: "ace/theme/" + name, - isDark: data[2] == "dark", - name: name - }; - exports.themesByName[name] = theme; - return theme; +module.exports.themes = require('ace/ext/themelist_utils/themes').themes; + +/** + * Creates a theme description. + * @param {string} name The file name of the theme. + * @returns {ThemeDescription} Returns a theme description object which has + * three properties: the name gives the filename, the desc gives a menu + * friendly name, and the theme gives the string to set the theme with + * `setTheme` + */ +module.exports.ThemeDescription = function(name) { + this.name = name; + this.desc = name.split('_' + ).map( + function(namePart) { + return namePart[0].toUpperCase() + namePart.slice(1); + } + ).join(' '); + this.theme = "ace/theme/" + name; +}; + +module.exports.themesByName = {}; + +module.exports.themes = module.exports.themes.map(function(name) { + module.exports.themesByName[name] = new module.exports.ThemeDescription(name); + return module.exports.themesByName[name]; }); }); diff --git a/lib/ace/ext/themelist_utils/themes.js b/lib/ace/ext/themelist_utils/themes.js new file mode 100644 index 00000000..2e490c9f --- /dev/null +++ b/lib/ace/ext/themelist_utils/themes.js @@ -0,0 +1,36 @@ +define(function(require, exports, module) { + +module.exports.themes = [ + "ambiance", + "chaos", + "chrome", + "clouds", + "clouds_midnight", + "cobalt", + "crimson_editor", + "dawn", + "dreamweaver", + "eclipse", + "github", + "idle_fingers", + "kr_theme", + "merbivore", + "merbivore_soft", + "mono_industrial", + "monokai", + "pastel_on_dark", + "solarized_dark", + "solarized_light", + "terminal", + "textmate", + "tomorrow", + "tomorrow_night", + "tomorrow_night_blue", + "tomorrow_night_bright", + "tomorrow_night_eighties", + "twilight", + "vibrant_ink", + "xcode" +]; + +}); \ No newline at end of file diff --git a/lib/ace/ext/whitespace.js b/lib/ace/ext/whitespace.js index 27ee223e..83486fb0 100644 --- a/lib/ace/ext/whitespace.js +++ b/lib/ace/ext/whitespace.js @@ -46,6 +46,7 @@ exports.$detectIndentation = function(lines, fallback) { if (!/^\s*[^*+\-\s]/.test(line)) continue; + var tabs = line.match(/^\t*/)[0].length; if (line[0] == "\t") tabIndents++; @@ -60,10 +61,10 @@ exports.$detectIndentation = function(lines, fallback) { prevSpaces = spaces; // ignore lines ending with backslash - while (i < max && line[line.length - 1] == "\\") + while (line[line.length - 1] == "\\") line = lines[i++]; } - + function getScore(indent) { var score = 0; for (var i = indent; i < stats.length; i += indent) @@ -76,17 +77,15 @@ exports.$detectIndentation = function(lines, fallback) { var first = {score: 0, length: 0}; var spaceIndents = 0; for (var i = 1; i < 12; i++) { - var score = getScore(i); if (i == 1) { - spaceIndents = score; - score = stats[1] ? 0.9 : 0.8; - if (!stats.length) - score = 0 + spaceIndents = getScore(i); + var score = 1; } else - score /= spaceIndents; + var score = getScore(i) / spaceIndents; - if (changes[i]) + if (changes[i]) { score += changes[i] / changesTotal; + } if (score > first.score) first = {score: score, length: i}; @@ -98,7 +97,7 @@ exports.$detectIndentation = function(lines, fallback) { if (tabIndents > spaceIndents + 1) return {ch: "\t", length: tabLength}; - if (spaceIndents > tabIndents + 1) + if (spaceIndents + 1 > tabIndents) return {ch: " ", length: tabLength}; }; diff --git a/lib/ace/ext/whitespace_test.js b/lib/ace/ext/whitespace_test.js deleted file mode 100644 index be4f360f..00000000 --- a/lib/ace/ext/whitespace_test.js +++ /dev/null @@ -1,116 +0,0 @@ -if (typeof process !== "undefined") { - require("amd-loader"); - require("../test/mockdom"); -} - -define(function(require, exports, module) { -"use strict"; - -var assert = require("assert"); -var EditSession = require("../edit_session").EditSession; -var whitespace = require("./whitespace"); - -// Execution ORDER: test.setUpSuite, setUp, testFn, tearDown, test.tearDownSuite -module.exports = { - timeout: 10000, - - "test tab detection": function(next) { - var s = new EditSession([ - "define({", - "\tfoo:1,", - "\tbar:2,", - "\tbaz:{,", - "\t\tx:3", - "\t}", - "})" - ]); - - var indent = whitespace.$detectIndentation(s.doc.$lines); - assert.equal(indent.ch, "\t"); - assert.equal(indent.length, undefined); - - s.insert({row: 0, column: 0}, " "); - indent = whitespace.$detectIndentation(s.doc.$lines); - assert.equal(indent.ch, "\t"); - assert.equal(indent.length, 4); - - s.setValue(""); - indent = whitespace.$detectIndentation(s.doc.$lines); - assert.ok(!indent); - - next(); - }, - - "test empty session": function(next) { - var s = new EditSession([ - "define({", - "foo:1,", - "})" - ]); - var indent = whitespace.$detectIndentation(s.doc.$lines); - assert.ok(!indent); - s.insert({row: 1, column: 0}, " x\n "); - - indent = whitespace.$detectIndentation(s.doc.$lines); - assert.equal(indent.ch, " "); - assert.equal(indent.length, 4); - - next(); - }, - - "!test one line": function(next) { - var s = new EditSession([ - "define({", - " foo:1,", - "})" - ]); - var indent = whitespace.$detectIndentation(s.doc.$lines); - assert.equal(indent.ch, " "); - assert.equal(indent.length, 4); - - next(); - }, - - "test 1 width indents": function(next) { - var s = new EditSession([ - "define({", - " foo:1,", - "})", - "define({", - " bar:1,", - "})", - " t", - " t", - " t", - " t", - " t", - " t", - " t", - " t" - ]); - var indent = whitespace.$detectIndentation(s.doc.$lines); - // assert.equal(indent.ch, " "); - // assert.equal(indent.length, 4); - - s = new EditSession([ - "{", - " foo:1,", - " bar: {", - " baz:2", - " }", - "}" - ]); - indent = whitespace.$detectIndentation(s.doc.$lines); - assert.equal(indent.ch, " "); - assert.equal(indent.length, 1); - - next(); - }, - -}; - -}); - -if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec(); -} diff --git a/lib/ace/incremental_search.js b/lib/ace/incremental_search.js index e4c1bdf8..e6fa8928 100644 --- a/lib/ace/incremental_search.js +++ b/lib/ace/incremental_search.js @@ -64,34 +64,6 @@ function IncrementalSearch() { oop.inherits(IncrementalSearch, Search); -// regexp handling - -function isRegExp(obj) { - return obj instanceof RegExp; -} - -function regExpToObject(re) { - var string = String(re), - start = string.indexOf('/'), - flagStart = string.lastIndexOf('/'); - return { - expression: string.slice(start+1, flagStart), - flags: string.slice(flagStart+1) - } -} - -function stringToRegExp(string, flags) { - try { - return new RegExp(string, flags); - } catch (e) { return string; } -} - -function objectToRegExp(obj) { - return stringToRegExp(obj.expression, obj.flags); -} - -// iSearch class - ;(function() { this.activate = function(ed, backwards) { @@ -100,24 +72,20 @@ function objectToRegExp(obj) { this.$options.needle = ''; this.$options.backwards = backwards; ed.keyBinding.addKeyboardHandler(this.$keyboardHandler); - // we need to completely intercept paste, just registering an event handler does not work - this.$originalEditorOnPaste = ed.onPaste; ed.onPaste = this.onPaste.bind(this); this.$mousedownHandler = ed.addEventListener('mousedown', this.onMouseDown.bind(this)); this.selectionFix(ed); this.statusMessage(true); - }; + } this.deactivate = function(reset) { this.cancelSearch(reset); - var ed = this.$editor; - ed.keyBinding.removeKeyboardHandler(this.$keyboardHandler); + this.$editor.keyBinding.removeKeyboardHandler(this.$keyboardHandler); if (this.$mousedownHandler) { - ed.removeEventListener('mousedown', this.$mousedownHandler); + this.$editor.removeEventListener('mousedown', this.$mousedownHandler); delete this.$mousedownHandler; } - ed.onPaste = this.$originalEditorOnPaste; this.message(''); - }; + } this.selectionFix = function(editor) { // Fix selection bug: When clicked inside the editor @@ -128,7 +96,7 @@ function objectToRegExp(obj) { if (editor.selection.isEmpty() && !editor.session.$emacsMark) { editor.clearSelection(); } - }; + } this.highlight = function(regexp) { var sess = this.$editor.session, @@ -136,7 +104,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 +118,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,46 +131,36 @@ 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; var session = this.$editor.session, - found = this.find(session), - shouldSelect = this.$editor.emacsMark ? - !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); + found = this.find(session); if (found) { if (options.backwards) found = Range.fromPoints(found.end, found.start); - this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end)); + this.$editor.moveCursorToPosition(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) { + this.addChar = function(c) { return this.highlightAndFindWithNeedle(false, function(needle) { - if (!isRegExp(needle)) - return needle + s; - var reObj = regExpToObject(needle); - reObj.expression += s; - return objectToRegExp(reObj); + return needle + c; }); - }; + } this.removeChar = function(c) { return this.highlightAndFindWithNeedle(false, function(needle) { - if (!isRegExp(needle)) - return needle.substring(0, needle.length-1); - var reObj = regExpToObject(needle); - reObj.expression = reObj.expression.substring(0, reObj.expression.length-1); - return objectToRegExp(reObj); + return needle.length > 0 ? needle.substring(0, needle.length-1) : needle; }); - }; + } this.next = function(options) { // try to find the next occurence of whatever we have searched for @@ -215,29 +173,13 @@ 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 +187,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 +196,7 @@ function objectToRegExp(obj) { } else { console.log(msg); } - }; + } }).call(IncrementalSearch.prototype); diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index d1303b42..c351d8e2 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,17 +35,13 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -var emacs = require('./keyboard/emacs'); var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; var MockRenderer = require("./test/mockrenderer").MockRenderer; var Range = require("./range").Range; -var MultiSelect = require("./multi_select").MultiSelect; var assert = require("./test/assertions"); var IncrementalSearch = require("./incremental_search").IncrementalSearch; -require("./multi_select"); - var editor, iSearch; function testRanges(str, ranges) { ranges = ranges || editor.selection.getAllRanges(); @@ -73,7 +69,6 @@ module.exports = { setUp: function() { var session = new EditSession(["abc123", "xyz124"]); editor = new Editor(new MockRenderer(), session); - new MultiSelect(editor); iSearch = new IncrementalSearch(); }, @@ -100,17 +95,17 @@ module.exports = { "test: find simple text incrementally" : function() { iSearch.activate(editor); - var range = iSearch.addString('1'), // "1" + var range = iSearch.addChar('1'), // "1" highlightRanges = callHighlighterUpdate(editor.session); testRanges("Range: [0/3] -> [0/4]", [range], "range"); testRanges("Range: [0/3] -> [0/4],Range: [1/3] -> [1/4]", highlightRanges, "highlight"); - range = iSearch.addString('2'); // "12" + range = iSearch.addChar('2'); // "12" highlightRanges = callHighlighterUpdate(editor.session); testRanges("Range: [0/3] -> [0/5]", [range], "range"); testRanges("Range: [0/3] -> [0/5],Range: [1/3] -> [1/5]", highlightRanges, "highlight"); - range = iSearch.addString('3'); // "123" + range = iSearch.addChar('3'); // "123" highlightRanges = callHighlighterUpdate(editor.session); testRanges("Range: [0/3] -> [0/6]", [range], "range"); testRanges("Range: [0/3] -> [0/6]", highlightRanges, "highlight"); @@ -123,7 +118,7 @@ module.exports = { "test: forward / backward" : function() { iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); + iSearch.addChar('1'); iSearch.addChar('2'); var range = iSearch.next(); testRanges("Range: [1/3] -> [1/5]", [range], "range"); @@ -136,18 +131,18 @@ module.exports = { "test: cancelSearch" : function() { iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); + iSearch.addChar('1'); iSearch.addChar('2'); var range = iSearch.cancelSearch(true); testRanges("Range: [0/0] -> [0/0]", [range], "range"); - iSearch.addString('1'); range = iSearch.addString('2'); + iSearch.addChar('1'); range = iSearch.addChar('2'); testRanges("Range: [0/3] -> [0/5]", [range], "range"); }, "test: failing search keeps pos" : function() { iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); - var range = iSearch.addString('x'); + iSearch.addChar('1'); iSearch.addChar('2'); + var range = iSearch.addChar('x'); testRanges("", [range], "range"); assert.position(editor.getCursorPosition(), 0, 5); }, @@ -155,14 +150,14 @@ module.exports = { "test: backwards search" : function() { editor.moveCursorTo(1,0); iSearch.activate(editor, true); - iSearch.addString('1'); var range = iSearch.addString('2');; + iSearch.addChar('1'); var range = iSearch.addChar('2');; testRanges("Range: [0/5] -> [0/3]", [range], "range"); assert.position(editor.getCursorPosition(), 0, 3); }, "test: forwards then backwards, same result, reoriented range" : function() { iSearch.activate(editor); - iSearch.addString('1'); var range = iSearch.addString('2');; + iSearch.addChar('1'); var range = iSearch.addChar('2');; testRanges("Range: [0/3] -> [0/5]", [range], "range"); assert.position(editor.getCursorPosition(), 0, 5); @@ -173,7 +168,7 @@ module.exports = { "test: reuse prev search via option" : function() { iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2');; + iSearch.addChar('1'); iSearch.addChar('2');; assert.position(editor.getCursorPosition(), 0, 5); iSearch.deactivate(); @@ -184,14 +179,14 @@ module.exports = { "test: don't extend selection range if selection is empty" : function() { iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2');; + iSearch.addChar('1'); iSearch.addChar('2');; testRanges("Range: [0/5] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, "test: extend selection range if selection exists" : function() { iSearch.activate(editor); editor.selection.selectTo(0, 1); - iSearch.addString('1'); iSearch.addString('2');; + iSearch.addChar('1'); iSearch.addChar('2');; testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, @@ -200,7 +195,7 @@ module.exports = { editor.keyBinding.addKeyboardHandler(emacs.handler); emacs.handler.commands.setMark.exec(editor); iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); + iSearch.addChar('1'); iSearch.addChar('2');; testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); } diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 8cecad1b..1cb84f59 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -64,14 +64,14 @@ exports.handler.attach = function(editor) { initialized = true; dom.importCssString('\ .emacs-mode .ace_cursor{\ - border: 1px rgba(50,250,50,0.8) solid!important;\ + border: 2px rgba(50,250,50,0.8) solid!important;\ -moz-box-sizing: border-box!important;\ -webkit-box-sizing: border-box!important;\ box-sizing: border-box!important;\ background-color: rgba(0,250,0,0.9);\ opacity: 0.5;\ }\ - .emacs-mode .ace_hidden-cursors .ace_cursor{\ + .emacs-mode .ace_cursor.ace_hidden{\ opacity: 1;\ background-color: transparent;\ }\ @@ -100,47 +100,29 @@ exports.handler.attach = function(editor) { editor.emacsMark = function() { return this.session.$emacsMark; - }; + } editor.setEmacsMark = function(p) { // to deactivate pass in a falsy value this.session.$emacsMark = p; - }; + } editor.pushEmacsMark = function(p, activate) { var prevMark = this.session.$emacsMark; if (prevMark) this.session.$emacsMarkRing.push(prevMark); - if (!p || activate) this.setEmacsMark(p); + if (!p || activate) this.setEmacsMark(p) else this.session.$emacsMarkRing.push(p); - }; + } editor.popEmacsMark = function() { var mark = this.emacsMark(); if (mark) { this.setEmacsMark(null); return mark; } return this.session.$emacsMarkRing.pop(); - }; + } editor.getLastEmacsMark = function(p) { return this.session.$emacsMark || this.session.$emacsMarkRing.slice(-1)[0]; - }; - - editor.emacsMarkForSelection = function(replacement) { - // find the mark in $emacsMarkRing corresponding to the current - // selection - var sel = this.selection, - multiRangeLength = this.multiSelect ? - this.multiSelect.getAllRanges().length : 1, - selIndex = sel.index || 0, - markRing = this.session.$emacsMarkRing, - markIndex = markRing.length - (multiRangeLength - selIndex), - lastMark = markRing[markIndex] || sel.anchor; - if (replacement) { - markRing.splice(markIndex, 1, - "row" in replacement && "column" in replacement ? - replacement : undefined); - } - return lastMark; } editor.on("click", $resetMarkMode); @@ -164,7 +146,6 @@ exports.handler.detach = function(editor) { editor.commands.removeCommands(commands); editor.removeEventListener('copy', this.onCopy); editor.removeEventListener('paste', this.onPaste); - editor.$emacsModeHandler = null; }; var $kbSessionChange = function(e) { @@ -182,15 +163,15 @@ var $kbSessionChange = function(e) { e.session.$emacsMark = null; if (!e.session.hasOwnProperty('$emacsMarkRing')) e.session.$emacsMarkRing = []; -}; +} var $resetMarkMode = function(e) { e.editor.session.$emacsMark = null; -}; +} -var keys = require("../lib/keys").KEY_MODS; -var eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"}; -var combinations = ["C-S-M-CMD", +var keys = require("../lib/keys").KEY_MODS, + eMods = {C: "ctrl", S: "shift", M: "alt", CMD: "command"}, + combinations = ["C-S-M-CMD", "S-M-CMD", "C-M-CMD", "C-S-CMD", "C-S-M", "M-CMD", "S-CMD", "S-M", "C-CMD", "C-M", "C-S", "CMD", "M", "S", "C"]; @@ -206,20 +187,18 @@ exports.handler.onCopy = function(e, editor) { if (editor.$handlesEmacsOnCopy) return; editor.$handlesEmacsOnCopy = true; exports.handler.commands.killRingSave.exec(editor); - editor.$handlesEmacsOnCopy = false; -}; + delete editor.$handlesEmacsOnCopy; +} exports.handler.onPaste = function(e, editor) { editor.pushEmacsMark(editor.getCursorPosition()); -}; +} exports.handler.bindKey = function(key, command) { - if (typeof key == "object") - key = key[this.platform]; if (!key) return; - var ckb = this.commandKeyBinding; + var ckb = this.commmandKeyBinding; key.split("|").forEach(function(keyPart) { keyPart = keyPart.toLowerCase(); ckb[keyPart] = command; @@ -227,7 +206,7 @@ exports.handler.bindKey = function(key, command) { // to be able to activate key combos with arbitrary length // Example: if keyPart is "C-c C-l t" then "C-c C-l t" will // get command assigned and "C-c" and "C-c C-l" will get - // a null command assigned in this.commandKeyBinding. For + // a null command assigned in this.commmandKeyBinding. For // the lookup logic see handleKeyboard() var keyParts = keyPart.split(" ").slice(0,-1); keyParts.reduce(function(keyMapKeys, keyPart, i) { @@ -237,45 +216,38 @@ exports.handler.bindKey = function(key, command) { if (!ckb[keyPart]) ckb[keyPart] = "null"; }); }, this); -}; - -exports.handler.getStatusText = function(editor, data) { - var str = ""; - if (data.count) - str += data.count; - if (data.keyChain) - str += " " + data.keyChain - return str; -}; +} exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { - // if keyCode == -1 a non-printable key was pressed, such as just - // control. Handling those is currently not supported in this handler - if (keyCode === -1) return undefined; - var editor = data.editor; - editor._signal("changeStatus"); // insertstring data.count times if (hashId == -1) { editor.pushEmacsMark(); if (data.count) { - var str = new Array(data.count + 1).join(key); + var str = Array(data.count + 1).join(key); data.count = null; return {command: "insertstring", args: str}; } } + if (key == "\x00") return undefined; + var modifier = eMods[hashId]; // CTRL + number / universalArgument for setting data.count - if (modifier == "c-" || data.count) { + if (modifier == "c-" || data.universalArgument) { + var prevCount = String(data.count || 0); var count = parseInt(key[key.length - 1]); if (typeof count === 'number' && !isNaN(count)) { - data.count = Math.max(data.count, 0) || 0; - data.count = 10 * data.count + count; + data.count = parseInt(prevCount + count); return {command: "null"}; + } else if (data.universalArgument) { + // if no number pressed use emacs defaults for universalArgument + // which is 4 + data.count = 4; } } + data.universalArgument = false; // this.commandKeyBinding maps key specs like "c-p" (for CTRL + P) to // command objects, for lookup key needs to include the modifier @@ -285,9 +257,9 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { if (data.keyChain) key = data.keyChain += " " + key; // Key combo prefixes get stored as "null" (String!) in this - // this.commandKeyBinding. When encountered no command is invoked but we + // this.commmandKeyBinding. When encountered no command is invoked but we // buld up data.keyChain - var command = this.commandKeyBinding[key]; + var command = this.commmandKeyBinding[key]; data.keyChain = command == "null" ? key : ""; // there really is no command @@ -297,9 +269,7 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { if (command === "null") return {command: "null"}; if (command === "universalArgument") { - // if no number pressed emacs repeats action 4 times. - // minus sign is needed to allow next keypress to replace it - data.count = -4; + data.universalArgument = true; return {command: "null"}; } @@ -326,12 +296,9 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { if (!command) return undefined; } - if (!command.readOnly && !command.isYank) + if (!command.readonly && !command.isYank) data.lastCommand = null; - if (!command.readOnly && editor.emacsMark()) - editor.setEmacsMark(null) - if (data.count) { var count = data.count; data.count = 0; @@ -342,12 +309,11 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { exec: function(editor, args) { for (var i = 0; i < count; i++) command.exec(editor, args); - }, - multiSelectAction: command.multiSelectAction + } } }; } else { - if (!args) args = {}; + if (!args) args = {} if (typeof args === 'object') args.count = count; } } @@ -414,7 +380,7 @@ exports.emacsKeys = { "M-y": "yankRotate", "C-g": "keyboardQuit", - "C-w|C-S-W": "killRegion", + "C-w": "killRegion", "M-w": "killRingSave", "C-Space": "setMark", "C-x C-x": "exchangePointAndMark", @@ -428,7 +394,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 "} @@ -464,65 +430,61 @@ exports.handler.addCommands({ // selection modification commands. That is, // "goto" commands become "select" commands. // Any insertion or mouse click resets mark-mode. - // setMark twice in a row at the same place resets markmode. - // in multi select mode, ea selection is handled individually - + // setMark twice in a row at the same place resets markmode if (args && args.count) { - if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark); - else moveToMark(); - moveToMark(); + var mark = editor.popEmacsMark(); + mark && editor.selection.moveCursorToPosition(mark); return; } var mark = editor.emacsMark(), - ranges = editor.selection.getAllRanges(), - rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }), - transientMarkModeActive = true, - hasNoSelection = ranges.every(function(range) { return range.isEmpty(); }); + transientMarkModeActive = true; + // if transientMarkModeActive then mark behavior is a little // 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)}); - else editor.clearSelection(); - if (mark) editor.pushEmacsMark(null); + if (transientMarkModeActive && (mark || !editor.selection.isEmpty())) { + editor.pushEmacsMark(); + editor.clearSelection(); return; } - if (!mark) { - rangePositions.forEach(function(pos) { editor.pushEmacsMark(pos); }); - editor.setEmacsMark(rangePositions[rangePositions.length-1]); - return; + if (mark) { + var cp = editor.getCursorPosition(); + if (editor.selection.isEmpty() && + mark.row == cp.row && mark.column == cp.column) { + editor.pushEmacsMark(); + return; + } } - - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - function moveToMark() { - var mark = editor.popEmacsMark(); - mark && editor.moveCursorToPosition(mark); - } - + // turn on mark mode + mark = editor.getCursorPosition(); + editor.setEmacsMark(mark); + editor.selection.setSelectionAnchor(mark.row, mark.column); }, - readOnly: true, - handlesCount: true + readonly: true, + handlesCount: true, + multiSelectAction: "forEach" }, exchangePointAndMark: { - exec: function exchangePointAndMark$exec(editor, args) { + exec: function(editor, args) { var sel = editor.selection; - if (!args.count && !sel.isEmpty()) { // just invert selection - sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); + if (args.count) { + var pos = editor.getCursorPosition(); + sel.clearSelection(); + sel.moveCursorToPosition(editor.popEmacsMark()); + editor.pushEmacsMark(pos); return; } - - if (args.count) { // replace mark and point - var pos = {row: sel.lead.row, column: sel.lead.column}; - sel.clearSelection(); - sel.moveCursorToPosition(editor.emacsMarkForSelection(pos)); - } else { // create selection to last mark - sel.selectToPosition(editor.emacsMarkForSelection()); + var lastMark = editor.getLastEmacsMark(); + var range = sel.getRange(); + if (range.isEmpty()) { + sel.selectToPosition(lastMark); + return; } + sel.setSelectionRange(range, !sel.isBackwards()); }, - readOnly: true, + readonly: true, handlesCount: true, multiSelectAction: "forEach" }, @@ -546,8 +508,8 @@ exports.handler.addCommands({ killLine: function(editor) { editor.pushEmacsMark(null); var pos = editor.getCursorPosition(); - if (pos.column === 0 && - editor.session.doc.getLine(pos.row).length === 0) { + if (pos.column == 0 && + editor.session.doc.getLine(pos.row).length == 0) { // If an already empty line is killed, remove // the line entirely editor.selection.selectLine(); @@ -573,7 +535,6 @@ exports.handler.addCommands({ if (editor.keyBinding.$data.lastCommand != "yank") return; editor.undo(); - editor.session.$emacsMarkRing.pop(); // also undo recording mark editor.onPaste(exports.killRing.rotate()); editor.keyBinding.$data.lastCommand = "yank"; }, @@ -582,38 +543,24 @@ exports.handler.addCommands({ exports.killRing.add(editor.getCopyText()); editor.commands.byName.cut.exec(editor); }, - readOnly: true, + readonly: true, multiSelectAction: "forEach" }, killRingSave: { exec: function(editor) { - // copy text and deselect. will save marks for starts of the - // selection(s) - - editor.$handlesEmacsOnCopy = true; - var marks = editor.session.$emacsMarkRing.slice(), - deselectedMarks = []; exports.killRing.add(editor.getCopyText()); - setTimeout(function() { - function deselect() { - var sel = editor.selection, range = sel.getRange(), - pos = sel.isBackwards() ? range.end : range.start; - deselectedMarks.push({row: pos.row, column: pos.column}); - sel.clearSelection(); - } - editor.$handlesEmacsOnCopy = false; - if (editor.inMultiSelectMode) editor.forEachSelection({exec: deselect}); - else deselect(); - editor.session.$emacsMarkRing = marks.concat(deselectedMarks.reverse()); + var sel = editor.selection, + range = sel.getRange(); + editor.pushEmacsMark(sel.isBackwards() ? range.end : range.start); + sel.clearSelection(); }, 0); }, - readOnly: true + readonly: true }, keyboardQuit: function(editor) { editor.selection.clearSelection(); editor.setEmacsMark(null); - editor.keyBinding.$data.count = null; }, focusCommandLine: function(editor, arg) { if (editor.showCommandLine) diff --git a/lib/ace/keyboard/emacs_test.js b/lib/ace/keyboard/emacs_test.js index 3ba5efaa..d1aba564 100644 --- a/lib/ace/keyboard/emacs_test.js +++ b/lib/ace/keyboard/emacs_test.js @@ -35,29 +35,17 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -require("../multi_select"); - var EditSession = require("./../edit_session").EditSession, Editor = require("./../editor").Editor, - Range = require("./../range").Range, MockRenderer = require("./../test/mockrenderer").MockRenderer, emacs = require('./emacs'), assert = require("./../test/assertions"), - editor, sel; + editor; function initEditor(docString) { var doc = new EditSession(docString.split("\n")); editor = new Editor(new MockRenderer(), doc); editor.setKeyboardHandler(emacs.handler); - sel = editor.selection; -} - -function print(obj) { - return JSON.stringify(obj, null, 2); -} - -function pluck(arr, what) { - return arr.map(function(ea) { return ea[what]; }); } module.exports = { @@ -74,72 +62,6 @@ module.exports = { editor.selectAll(); editor.execCommand('keyboardQuit'); assert.ok(editor.selection.isEmpty(), 'selection non-empty'); - }, - - "test: exchangePointAndMark without mark set": function() { - initEditor('foo'); - sel.setRange(Range.fromPoints({row: 0, column: 1}, {row: 0, column: 3})); - editor.execCommand('exchangePointAndMark'); - assert.deepEqual({row: 0, column: 1}, editor.getCursorPosition(), print(editor.getCursorPosition())); - }, - - "test: exchangePointAndMark with mark set": function() { - initEditor('foo'); - editor.pushEmacsMark({row: 0, column: 1}); - editor.pushEmacsMark({row: 0, column: 2}); - editor.execCommand('exchangePointAndMark', {count: 4}); - assert.deepEqual({row: 0, column: 2}, editor.getCursorPosition(), print(editor.getCursorPosition())); - assert.deepEqual([{row: 0, column: 1}, {row: 0, column: 0}], editor.session.$emacsMarkRing, print(editor.session.$emacsMarkRing)); - }, - - "test: exchangePointAndMark with selection": function() { - initEditor('foo'); - editor.pushEmacsMark({row: 0, column: 1}); - editor.pushEmacsMark({row: 0, column: 2}); - sel.setRange(Range.fromPoints({row: 0, column: 0}, {row: 0, column: 1}), true); - editor.execCommand('exchangePointAndMark'); - assert.deepEqual({row: 0, column: 1}, editor.getCursorPosition(), print(editor.getCursorPosition())); - assert.deepEqual([{row: 0, column: 1}, {row: 0, column: 2}], editor.session.$emacsMarkRing, print(editor.session.$emacsMarkRing)); - }, - - "test: exchangePointAndMark with multi selection": function() { - initEditor('foo\nhello world\n123'); - var ranges = [[{row: 0, column: 0}, {row: 0, column: 3}], - [{row: 1, column: 0}, {row: 1, column: 5}], - [{row: 1, column: 6}, {row: 1, column: 11}]] - ranges.forEach(function(r) { - sel.addRange(Range.fromPoints(r[0], r[1])); - }); - assert.equal("foo\nhello\nworld", editor.getSelectedText()); - editor.execCommand('exchangePointAndMark'); - assert.equal("foo\nhello\nworld", editor.getSelectedText()); - assert.deepEqual(pluck(ranges, 0), pluck(sel.getAllRanges(), 'cursor'), "selections dir not inverted"); - }, - - "test: exchangePointAndMark with multi cursors": function() { - initEditor('foo\nhello world\n123'); - var ranges = [[{row: 0, column: 0}, {row: 0, column: 3}], - [{row: 1, column: 0}, {row: 1, column: 5}], - [{row: 1, column: 6}, {row: 1, column: 11}]]; - // move cursors to the start of each range and set a mark to its end - // without selecting anything - ranges.forEach(function(r) { - editor.pushEmacsMark(r[1]); - sel.addRange(Range.fromPoints(r[0], r[0])); - }); - assert.deepEqual(pluck(ranges, 0), pluck(sel.getAllRanges(), 'cursor'), print(sel.getAllRanges())); - editor.execCommand('exchangePointAndMark'); - assert.deepEqual(pluck(ranges, 1), pluck(sel.getAllRanges(), 'cursor'), "not inverted: " + print(sel.getAllRanges())); - }, - - "test: setMark with multi cursors": function() { - initEditor('foo\nhello world\n123'); - var positions = [{row: 0, column: 0}, - {row: 1, column: 0}, - {row: 1, column: 6}]; - positions.forEach(function(p) { sel.addRange(Range.fromPoints(p,p)); }); - editor.execCommand('setMark'); - assert.deepEqual(positions, editor.session.$emacsMarkRing, print(editor.session.$emacsMarkRing)); } }; diff --git a/lib/ace/keyboard/hash_handler.js b/lib/ace/keyboard/hash_handler.js index a7dc1a93..f56532ee 100644 --- a/lib/ace/keyboard/hash_handler.js +++ b/lib/ace/keyboard/hash_handler.js @@ -33,25 +33,16 @@ define(function(require, exports, module) { var keyUtil = require("../lib/keys"); var useragent = require("../lib/useragent"); -var KEY_MODS = keyUtil.KEY_MODS; function HashHandler(config, platform) { this.platform = platform || (useragent.isMac ? "mac" : "win"); this.commands = {}; - this.commandKeyBinding = {}; + this.commmandKeyBinding = {}; + this.addCommands(config); - this.$singleCommand = true; -} - -function MultiHashHandler(config, platform) { - HashHandler.call(this, config, platform); - this.$singleCommand = false; -} - -MultiHashHandler.prototype = HashHandler.prototype; +}; (function() { - this.addCommand = function(command) { if (this.commands[command.name]) @@ -63,92 +54,36 @@ MultiHashHandler.prototype = HashHandler.prototype; this._buildKeyHash(command); }; - this.removeCommand = function(command, keepCommand) { - var name = command && (typeof command === 'string' ? command : command.name); + this.removeCommand = function(command) { + var name = (typeof command === 'string' ? command : command.name); command = this.commands[name]; - if (!keepCommand) - delete this.commands[name]; + delete this.commands[name]; // exhaustive search is brute force but since removeCommand is // not a performance critical operation this should be OK - var ckb = this.commandKeyBinding; - for (var keyId in ckb) { - var cmdGroup = ckb[keyId]; - if (cmdGroup == command) { - delete ckb[keyId]; - } else if (Array.isArray(cmdGroup)) { - var i = cmdGroup.indexOf(command); - if (i != -1) { - cmdGroup.splice(i, 1); - if (cmdGroup.length == 1) - ckb[keyId] = cmdGroup[0]; - } + var ckb = this.commmandKeyBinding; + for (var hashId in ckb) { + for (var key in ckb[hashId]) { + if (ckb[hashId][key] == command) + delete ckb[hashId][key]; } } }; - this.bindKey = function(key, command, position) { - if (typeof key == "object") { - if (position == undefined) - position = key.position; - key = key[this.platform]; - } - if (!key) + this.bindKey = function(key, command) { + if(!key) + return; + if (typeof command == "function") { + this.addCommand({exec: command, bindKey: key, name: command.name || key}); return; - if (typeof command == "function") - return this.addCommand({exec: command, bindKey: key, name: command.name || key}); - - key.split("|").forEach(function(keyPart) { - var chain = ""; - if (keyPart.indexOf(" ") != -1) { - var parts = keyPart.split(/\s+/); - keyPart = parts.pop(); - parts.forEach(function(keyPart) { - var binding = this.parseKeys(keyPart); - var id = KEY_MODS[binding.hashId] + binding.key; - chain += (chain ? " " : "") + id; - this._addCommandToBinding(chain, "chainKeys"); - }, this); - chain += " "; - } - var binding = this.parseKeys(keyPart); - var id = KEY_MODS[binding.hashId] + binding.key; - this._addCommandToBinding(chain + id, command, position); - }, this); - }; - - 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]; - } else if (!ckb[keyId] || this.$singleCommand) { - ckb[keyId] = command; - } else { - if (!Array.isArray(ckb[keyId])) { - ckb[keyId] = [ckb[keyId]]; - } else if ((i = ckb[keyId].indexOf(command)) != -1) { - ckb[keyId].splice(i, 1); - } - - 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); } + + var ckb = this.commmandKeyBinding; + key.split("|").forEach(function(keyPart) { + var binding = this.parseKeys(keyPart, command); + var hashId = binding.hashId; + (ckb[hashId] || (ckb[hashId] = {}))[binding.key] = command; + }, this); }; this.addCommands = function(commands) { @@ -163,9 +98,6 @@ MultiHashHandler.prototype = HashHandler.prototype; if (typeof command === "function") command = { exec: command }; - if (typeof command !== "object") - return; - if (!command.name) command.name = name; @@ -186,12 +118,21 @@ MultiHashHandler.prototype = HashHandler.prototype; }; this._buildKeyHash = function(command) { - this.bindKey(command.bindKey, command); + var binding = command.bindKey; + if (!binding) + return; + + var key = typeof binding == "string" ? binding: binding[this.platform]; + this.bindKey(key, command); }; // accepts keys in the form ctrl+Enter or ctrl-Enter // keys without modifiers or shift only this.parseKeys = function(keys) { + // todo support keychains + if (keys.indexOf(" ") != -1) + keys = keys.split(/\s+/).pop(); + var parts = keys.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(x){return x}); var key = parts.pop(); @@ -208,7 +149,7 @@ MultiHashHandler.prototype = HashHandler.prototype; var modifier = keyUtil.KEY_MODS[parts[i]]; if (modifier == null) { if (typeof console != "undefined") - console.error("invalid modifier " + parts[i] + " in " + keys); + console.error("invalid modifier " + parts[i] + " in " + keys); return false; } hashId |= modifier; @@ -217,40 +158,17 @@ MultiHashHandler.prototype = HashHandler.prototype; }; this.findKeyCommand = function findKeyCommand(hashId, keyString) { - var key = KEY_MODS[hashId] + keyString; - return this.commandKeyBinding[key]; + var ckbr = this.commmandKeyBinding; + return ckbr[hashId] && ckbr[hashId][keyString]; }; this.handleKeyboard = function(data, hashId, keyString, keyCode) { - var key = KEY_MODS[hashId] + keyString; - var command = this.commandKeyBinding[key]; - if (data.$keyChain) { - data.$keyChain += " " + key; - command = this.commandKeyBinding[data.$keyChain] || command; - } - - if (command) { - if (command == "chainKeys" || command[command.length - 1] == "chainKeys") { - data.$keyChain = data.$keyChain || key; - return {command: "null"}; - } - } - - 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 || ""; + return { + command: this.findKeyCommand(hashId, keyString) + }; }; -}).call(HashHandler.prototype); +}).call(HashHandler.prototype) exports.HashHandler = HashHandler; -exports.MultiHashHandler = MultiHashHandler; }); diff --git a/lib/ace/keyboard/keybinding.js b/lib/ace/keyboard/keybinding.js index cddf0666..2a1a2230 100644 --- a/lib/ace/keyboard/keybinding.js +++ b/lib/ace/keyboard/keybinding.js @@ -36,7 +36,7 @@ var event = require("../lib/event"); var KeyBinding = function(editor) { this.$editor = editor; - this.$data = {editor: editor}; + this.$data = { }; this.$handlers = []; this.setDefaultHandler(editor.commands); }; @@ -46,6 +46,7 @@ var KeyBinding = function(editor) { this.removeKeyboardHandler(this.$defaultHandler); this.$defaultHandler = kb; this.addKeyboardHandler(kb, 0); + this.$data = {editor: this.$editor}; }; this.setKeyboardHandler = function(kb) { @@ -62,8 +63,6 @@ var KeyBinding = function(editor) { this.addKeyboardHandler = function(kb, pos) { if (!kb) return; - if (typeof kb == "function" && !kb.handleKeyboard) - kb.handleKeyboard = kb; var i = this.$handlers.indexOf(kb); if (i != -1) this.$handlers.splice(i, 1); @@ -89,16 +88,8 @@ var KeyBinding = function(editor) { this.getKeyboardHandler = function() { return this.$handlers[this.$handlers.length - 1]; }; - - this.getStatusText = function() { - var data = this.$data; - var editor = data.editor; - return this.$handlers.map(function(h) { - return h.getStatusText && h.getStatusText(editor, data) || ""; - }).filter(Boolean).join(" "); - }; - this.$callKeyboardHandlers = function(hashId, keyString, keyCode, e) { + this.$callKeyboardHandlers = function (hashId, keyString, keyCode, e) { var toExecute; var success = false; var commands = this.$editor.commands; diff --git a/lib/ace/keyboard/textarea.js b/lib/ace/keyboard/textarea.js deleted file mode 100644 index 470b2940..00000000 --- a/lib/ace/keyboard/textarea.js +++ /dev/null @@ -1,82 +0,0 @@ -/* ***** 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 HashHandler = require("./hash_handler").HashHandler; -exports.handler = new HashHandler(); - -[{ - bindKey: "Shift-Tab|Tab", - command: "passKeysToBrowser" -}, { - bindKey: {win: "Ctrl-L", mac: "Cmd-L"}, - command: "passKeysToBrowser" -}, { - bindKey: {win: "Ctrl-G", mac: "Cmd-G"}, - command: "gotoline" -}, { - bindKey: {win: "Ctrl-T|Ctrl-Shift-T", mac: "Cmd-T|Cmd-Shift-T"}, - command: "passKeysToBrowser" -}, { - bindKey: {win: "Ctrl-G", mac: "Cmd-G"}, - command: "passKeysToBrowser" -}, { - bindKey: {win: "Ctrl-G", mac: "Cmd-G"}, - command: "passKeysToBrowser" -}, { - name: "golineup", - bindKey: {win: null, mac: "Ctrl-P"}, -}, { - name: "golinedown", - bindKey: {win: null, mac: "Ctrl-N"}, -}, { - name: "gotoleft", - bindKey: {win: null, mac: "Ctrl-B"}, -}, { - name: "gotoright", - bindKey: {win: null, mac: "Ctrl-F"}, -}, { - name: "gotolineend", - bindKey: {win: null, mac: "Ctrl-E"}, -}, { - name: "gotolinestart", - bindKey: {win: null, mac: "Ctrl-A"}, -} -].forEach(function(k) { - var bindKey = k.bindKey; - if (typeof bindKey == "object") - bindKey = bindKey[exports.handler.platform]; - exports.handler.bindKey(bindKey, k.command); -}); -exports.handler.$id = "ace/keyboard/textarea"; - -}); diff --git a/lib/ace/keyboard/textinput.js b/lib/ace/keyboard/textinput.js index 4a2bb72c..f0830e71 100644 --- a/lib/ace/keyboard/textinput.js +++ b/lib/ace/keyboard/textinput.js @@ -36,26 +36,27 @@ var useragent = require("../lib/useragent"); var dom = require("../lib/dom"); var lang = require("../lib/lang"); var BROKEN_SETDATA = useragent.isChrome < 18; -var USE_IE_MIME_TYPE = useragent.isIE; var TextInput = function(parentNode, host) { var text = dom.createElement("textarea"); text.className = "ace_text-input"; - + /*/ debug + text.style.cssText = "opacity:1;background:rgba(0, 250, 0, 0.3);outline:rgba(0, 250, 0, 0.8) solid 1px;outline-offset:3px;width:5em;z-pindex:500"; + /**/ if (useragent.isTouchPad) text.setAttribute("x-palm-disable-auto-cap", true); - text.setAttribute("wrap", "off"); - text.setAttribute("autocorrect", "off"); - text.setAttribute("autocapitalize", "off"); - text.setAttribute("spellcheck", false); + text.wrap = "off"; + text.autocorrect = "off"; + text.autocapitalize = "off"; + text.spellcheck = false; text.style.opacity = "0"; - if (useragent.isOldIE) text.style.top = "-1000px"; parentNode.insertBefore(text, parentNode.firstChild); var PLACEHOLDER = "\x01\x01"; + var cut = false; var copied = false; var pasted = false; var inComposition = false; @@ -66,24 +67,16 @@ var TextInput = function(parentNode, host) { // ie9 throws error if document.activeElement is accessed too soon try { var isFocused = document.activeElement === text; } catch(e) {} - event.addListener(text, "blur", function(e) { - host.onBlur(e); + event.addListener(text, "blur", function() { + host.onBlur(); isFocused = false; }); - event.addListener(text, "focus", function(e) { + event.addListener(text, "focus", function() { isFocused = true; - host.onFocus(e); + host.onFocus(); resetSelection(); }); - this.focus = function() { - if (tempStyle) return text.focus(); - text.style.position = "fixed"; - text.style.top = "-1000px"; - text.focus(); - setTimeout(function() { - text.style.position = ""; - }, 0); - }; + this.focus = function() { text.focus(); }; this.blur = function() { text.blur(); }; this.isFocused = function() { return isFocused; @@ -103,11 +96,6 @@ var TextInput = function(parentNode, host) { function resetSelection(isEmpty) { if (inComposition) return; - - // this prevents infinite recursion on safari 8 - // see https://github.com/ajaxorg/ace/issues/2114 - inComposition = true; - if (inputHandler) { selectionStart = 0; selectionEnd = isEmpty ? 0 : text.value.length - 1; @@ -119,8 +107,6 @@ var TextInput = function(parentNode, host) { try { text.setSelectionRange(selectionStart, selectionEnd); } catch(e){} - - inComposition = false; } function resetValue() { @@ -202,7 +188,9 @@ var TextInput = function(parentNode, host) { } var onSelect = function(e) { - if (copied) { + if (cut) { + cut = false; + } else if (copied) { copied = false; } else if (isAllSelected(text)) { host.selectAll(); @@ -230,8 +218,6 @@ var TextInput = function(parentNode, host) { } else if (data == PLACEHOLDER.charAt(0)) { if (afterContextMenu) host.execCommand("del", {source: "ace"}); - else // some versions of android do not fire keydown when pressing backspace - host.execCommand("backspace", {source: "ace"}); } else { if (data.substring(0, 2) == PLACEHOLDER) data = data.substr(2); @@ -257,31 +243,55 @@ var TextInput = function(parentNode, host) { sendText(data); resetValue(); }; - - var handleClipboardData = function(e, data) { - var clipboardData = e.clipboardData || window.clipboardData; - if (!clipboardData || BROKEN_SETDATA) + + var onCut = function(e) { + var data = host.getCopyText(); + if (!data) { + event.preventDefault(e); return; - // using "Text" doesn't work on old webkit but ie needs it - // TODO are there other browsers that require "Text"? - var mime = USE_IE_MIME_TYPE ? "Text" : "text/plain"; - if (data) { + } + + var clipboardData = e.clipboardData || window.clipboardData; + + if (clipboardData && !BROKEN_SETDATA) { // Safari 5 has clipboardData object, but does not handle setData() - return clipboardData.setData(mime, data) !== false; - } else { - return clipboardData.getData(mime); + var supported = clipboardData.setData("Text", data); + if (supported) { + host.onCut(); + event.preventDefault(e); + } + } + + if (!supported) { + cut = true; + text.value = data; + text.select(); + setTimeout(function(){ + cut = false; + resetValue(); + resetSelection(); + host.onCut(); + }); } }; - var doCopy = function(e, isCut) { + var onCopy = function(e) { var data = host.getCopyText(); - if (!data) - return event.preventDefault(e); - - if (handleClipboardData(e, data)) { - isCut ? host.onCut() : host.onCopy(); + if (!data) { event.preventDefault(e); - } else { + return; + } + + var clipboardData = e.clipboardData || window.clipboardData; + if (clipboardData && !BROKEN_SETDATA) { + // Safari 5 has clipboardData object, but does not handle setData() + var supported = clipboardData.setData("Text", data); + if (supported) { + host.onCopy(); + event.preventDefault(e); + } + } + if (!supported) { copied = true; text.value = data; text.select(); @@ -289,24 +299,18 @@ var TextInput = function(parentNode, host) { copied = false; resetValue(); resetSelection(); - isCut ? host.onCut() : host.onCopy(); + host.onCopy(); }); } }; - - var onCut = function(e) { - doCopy(e, true); - }; - - var onCopy = function(e) { - doCopy(e, false); - }; - + var onPaste = function(e) { - var data = handleClipboardData(e); - if (typeof data == "string") { + var clipboardData = e.clipboardData || window.clipboardData; + + if (clipboardData) { + var data = clipboardData.getData("Text"); if (data) - host.onPaste(data, e); + host.onPaste(data); if (useragent.isIE) setTimeout(resetSelection); event.preventDefault(e); @@ -332,7 +336,7 @@ var TextInput = function(parentNode, host) { if (!('oncut' in text) || !('oncopy' in text) || !('onpaste' in text)){ event.addListener(parentNode, "keydown", function(e) { if ((useragent.isMac && !e.metaKey) || !e.ctrlKey) - return; + return; switch (e.keyCode) { case 67: @@ -351,8 +355,7 @@ var TextInput = function(parentNode, host) { // COMPOSITION var onCompositionStart = function(e) { - if (inComposition || !host.onCompositionStart || host.$readOnly) - return; + if (inComposition) return; // console.log("onCompositionStart", inComposition) inComposition = {}; host.onCompositionStart(); @@ -368,8 +371,7 @@ var TextInput = function(parentNode, host) { var onCompositionUpdate = function() { // console.log("onCompositionUpdate", inComposition && JSON.stringify(text.value)) - if (!inComposition || !host.onCompositionUpdate || host.$readOnly) - return; + if (!inComposition) return; var val = text.value.replace(/\x01/g, ""); if (inComposition.lastValue === val) return; @@ -388,16 +390,14 @@ var TextInput = function(parentNode, host) { }; var onCompositionEnd = function(e) { - if (!host.onCompositionEnd || host.$readOnly) return; // console.log("onCompositionEnd", inComposition &&inComposition.lastValue) var c = inComposition; inComposition = false; var timer = setTimeout(function() { - timer = null; var str = text.value.replace(/\x01/g, ""); // console.log(str, c.lastValue) if (inComposition) - return; + return else if (str == c.lastValue) resetValue(); else if (!c.lastValue && str) { @@ -407,15 +407,14 @@ var TextInput = function(parentNode, host) { }); inputHandler = function compositionInputHandler(str) { // console.log("onCompositionEnd", str, c.lastValue) - if (timer) - clearTimeout(timer); + clearTimeout(timer); str = str.replace(/\x01/g, ""); if (str == c.lastValue) return ""; - if (c.lastValue && timer) + if (c.lastValue) host.undo(); return str; - }; + } host.onCompositionEnd(); host.removeListener("mousedown", onCompositionEnd); if (e.type == "compositionend" && c.range) { @@ -446,25 +445,19 @@ var TextInput = function(parentNode, host) { this.onContextMenu = function(e) { afterContextMenu = true; - resetSelection(host.selection.isEmpty()); - host._emit("nativecontextmenu", {target: host, domEvent: e}); - this.moveToMouse(e, true); - }; - - this.moveToMouse = function(e, bringToFront) { - if (!bringToFront && useragent.isOldIE) - return; if (!tempStyle) tempStyle = text.style.cssText; - text.style.cssText = (bringToFront ? "z-index:100000;" : "") - + "height:" + text.style.height + ";" - + (useragent.isIE ? "opacity:0.1;" : ""); + text.style.cssText = "z-index:100000;" + (useragent.isIE ? "opacity:0.1;" : ""); + //debug*/ text.style.cssText += "background:rgba(250, 0, 0, 0.3); opacity:1;"; + + resetSelection(host.selection.isEmpty()); + host._emit("nativecontextmenu", {target: host, domEvent: e}); var rect = host.container.getBoundingClientRect(); var style = dom.computedStyle(host.container); var top = rect.top + (parseInt(style.borderTopWidth) || 0); var left = rect.left + (parseInt(rect.borderLeftWidth) || 0); - var maxTop = rect.bottom - top - text.clientHeight -2; + var maxTop = rect.bottom - top - text.clientHeight; var move = function(e) { text.style.left = e.clientX - left - 2 + "px"; text.style.top = Math.min(e.clientY - top - 2, maxTop) + "px"; @@ -478,15 +471,13 @@ var TextInput = function(parentNode, host) { host.renderer.$keepTextAreaAtCursor = null; // on windows context menu is opened after mouseup - if (useragent.isWin && !useragent.isOldIE) + if (useragent.isWin) event.capture(host.container, move, onContextMenuClose); }; this.onContextMenuClose = onContextMenuClose; - var closeTimeout; function onContextMenuClose() { - clearTimeout(closeTimeout) - closeTimeout = setTimeout(function () { + setTimeout(function () { if (tempStyle) { text.style.cssText = tempStyle; tempStyle = ''; @@ -495,15 +486,16 @@ var TextInput = function(parentNode, host) { host.renderer.$keepTextAreaAtCursor = true; host.renderer.$moveTextAreaToCursor(); } - }, useragent.isOldIE ? 200 : 0); + }, 0); } - var onContextMenu = function(e) { - host.textInput.onContextMenu(e); - onContextMenuClose(); - }; - event.addListener(host.renderer.scroller, "contextmenu", onContextMenu); - event.addListener(text, "contextmenu", onContextMenu); + // firefox fires contextmenu event after opening it + if (!useragent.isGecko || useragent.isMac) { + event.addListener(text, "contextmenu", function(e) { + host.textInput.onContextMenu(e); + onContextMenuClose(); + }); + } }; exports.TextInput = TextInput; diff --git a/lib/ace/keyboard/vim.js b/lib/ace/keyboard/vim.js index 17c26c16..7af83b05 100644 --- a/lib/ace/keyboard/vim.js +++ b/lib/ace/keyboard/vim.js @@ -1,6177 +1,195 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Supported keybindings: +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: * - * Motion: - * h, j, k, l - * gj, gk - * e, E, w, W, b, B, ge, gE - * f, F, t, T - * $, ^, 0, -, +, _ - * gg, G - * % - * ', ` + * 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. * - * Operator: - * d, y, c - * dd, yy, cc - * g~, g~g~ - * >, <, >>, << - * - * Operator-Motion: - * x, X, D, Y, C, ~ - * - * Action: - * a, i, s, A, I, S, o, O - * zz, z., z, zt, zb, z- - * J - * u, Ctrl-r - * m - * r - * - * Modes: - * ESC - leave insert mode, visual mode, and clear input state. - * Ctrl-[, Ctrl-c - same as ESC. - * - * Registers: unnamed, -, a-z, A-Z, 0-9 - * (Does not respect the special case for number registers when delete - * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) - * TODO: Implement the remaining registers. - * Marks: a-z, A-Z, and 0-9 - * TODO: Implement the remaining special marks. They have more complex - * behavior. - * - * Events: - * 'vim-mode-change' - raised on the editor anytime the current mode changes, - * Event object: {mode: "visual", subMode: "linewise"} - * - * Code structure: - * 1. Default keymap - * 2. Variable declarations and short basic helpers - * 3. Instance (External API) implementation - * 4. Internal state tracking objects (input state, counter) implementation - * and instanstiation - * 5. Key handler (the main command dispatcher) implementation - * 6. Motion, operator, and action implementations - * 7. Helper functions for the key handler, motions, operators, and actions - * 8. Set up Vim to work as a keymap for CodeMirror. - */ + * ***** END LICENSE BLOCK ***** */ define(function(require, exports, module) { - 'use strict'; +"use strict"; - function log() { - var d = ""; - function format(p) { - if (typeof p != "object") - return p + ""; - if ("line" in p) { - return p.line + ":" + p.ch; - } - if ("anchor" in p) { - return format(p.anchor) + "->" + format(p.head); - } - if (Array.isArray(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 + " "; - } - console.log(d); - } - var Range = require("../range").Range; - var EventEmitter = require("../lib/event_emitter").EventEmitter; - var dom = require("../lib/dom"); - var oop = require("../lib/oop"); - var KEYS = require("../lib/keys"); - var event = require("../lib/event"); - var Search = require("../search").Search; - 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 cmds = require("./vim/commands"); +var coreCommands = cmds.coreCommands; +var util = require("./vim/maps/util"); +var useragent = require("../lib/useragent"); - var CodeMirror = function(ace) { - this.ace = ace; - this.state = {}; - this.marks = {}; - this.$uid = 0; - this.onChange = this.onChange.bind(this); - this.onSelectionChange = this.onSelectionChange.bind(this); - this.onBeforeEndOperation = this.onBeforeEndOperation.bind(this); - this.ace.on('change', this.onChange); - this.ace.on('changeSelection', this.onSelectionChange); - this.ace.on('beforeEndOperation', this.onBeforeEndOperation); - }; - CodeMirror.Pos = function(line, ch) { - if (!(this instanceof Pos)) return new Pos(line, ch); - this.line = line; this.ch = ch; - }; - CodeMirror.defineOption = function(name, val, setter) {}; - CodeMirror.commands = { - redo: function(cm) { cm.ace.redo(); }, - undo: function(cm) { cm.ace.undo(); }, - newlineAndIndent: function(cm) { cm.ace.insert("\n"); }, - }; - CodeMirror.keyMap = {}; - CodeMirror.addClass = CodeMirror.rmClass = - CodeMirror.e_stop = function() {}; - CodeMirror.keyName = function(e) { - if (e.key) return e.key; - var key = (KEYS[e.keyCode] || ""); - if (key.length == 1) key = key.toUpperCase(); - key = event.getModifierString(e).replace(/(^|-)\w/g, function(m) { - return m.toUpperCase(); - }) + key; - return key; - }; - CodeMirror.keyMap['default'] = function(key) { - return function(cm) { - var cmd = cm.ace.commands.commandKeyBinding[key.toLowerCase()]; - return cmd && cm.ace.execCommand(cmd) !== false; - }; - }; - CodeMirror.lookupKey = function lookupKey(key, map, handle) { - if (typeof map == "string") - map = CodeMirror.keyMap[map]; - var found = typeof map == "function" ? map(key) : map[key]; - if (found === false) return "nothing"; - if (found === "...") return "multi"; - if (found != null && handle(found)) return "handled"; - - if (map.fallthrough) { - if (!Array.isArray(map.fallthrough)) - return lookupKey(key, map.fallthrough, handle); - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle); - if (result) return result; - } - } - }; - - 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); - - this.destroy = function() { - this.ace.off('change', this.onChange); - this.ace.off('changeSelection', this.onSelectionChange); - this.ace.off('beforeEndOperation', this.onBeforeEndOperation); - this.removeOverlay(); - }; - this.virtualSelectionMode = function() { - return this.ace.inVirtualSelectionMode && this.ace.selection.index; - }; - this.onChange = function(delta) { - if (delta.action[0] == 'i') { - var change = { text: delta.lines }; - var curOp = this.curOp = this.curOp || {}; - if (!curOp.changeHandlers) - curOp.changeHandlers = this._eventRegistry["change"] && this._eventRegistry["change"].slice(); - if (this.virtualSelectionMode()) return; - if (!curOp.lastChange) { - curOp.lastChange = curOp.change = change; - } else { - curOp.lastChange.next = curOp.lastChange = change; - } - } - this.$updateMarkers(delta); - }; - this.onSelectionChange = function() { - var curOp = this.curOp = this.curOp || {}; - if (!curOp.cursorActivityHandlers) - curOp.cursorActivityHandlers = this._eventRegistry["cursorActivity"] && this._eventRegistry["cursorActivity"].slice(); - this.curOp.cursorActivity = true; - if (this.ace.inMultiSelectMode) { - this.ace.keyBinding.removeKeyboardHandler(multiSelectCommands.keyboardHandler); - } - }; - this.operation = function(fn, force) { - if (!force && this.curOp || force && this.curOp && this.curOp.force) { - return fn(); - } - if (force || !this.ace.curOp) { - if (this.curOp) - this.onBeforeEndOperation(); - } - if (!this.ace.curOp) { - var prevOp = this.ace.prevOp; - this.ace.startOperation({ - command: { name: "vim", scrollIntoView: "cursor" } - }); - } - var curOp = this.curOp = this.curOp || {}; - this.curOp.force = force; - var result = fn(); - if (this.ace.curOp && this.ace.curOp.command.name == "vim") { - this.ace.endOperation(); - if (!curOp.cursorActivity && !curOp.lastChange && prevOp) - this.ace.prevOp = prevOp; - } - if (force || !this.ace.curOp) { - if (this.curOp) - this.onBeforeEndOperation(); - } - return result; - }; - this.onBeforeEndOperation = function() { - var op = this.curOp; - if (op) { - if (op.change) { this.signal("change", op.change, op); } - if (op && op.cursorActivity) { this.signal("cursorActivity", null, op); } - this.curOp = null; - } - }; - - this.signal = function(eventName, e, handlers) { - var listeners = handlers ? handlers[eventName + "Handlers"] - : (this._eventRegistry || {})[eventName]; - if (!listeners) - return; - listeners = listeners.slice(); - for (var i=0; i 0) { - point.row += rowShift; - point.column += point.row == end.row ? colShift : 0; - continue; - } - if (!isInsert && cmp2 <= 0) { - point.row = start.row; - point.column = start.column; - if (cmp2 === 0) - point.bias = 1; - } - } - }; - var Marker = function(cm, id, row, column) { - this.cm = cm; - this.id = id; - this.row = row; - this.column = column; - cm.marks[this.id] = this; - }; - Marker.prototype.clear = function() { delete this.cm.marks[this.id] }; - Marker.prototype.find = function() { return toCmPos(this) }; - this.setBookmark = function(cursor, options) { - var bm = new Marker(this, this.$uid++, cursor.line, cursor.ch); - if (!options || !options.insertLeft) - bm.$insertRight = true; - this.marks[bm.id] = bm; - return bm; - }; - this.moveH = function(increment, unit) { - if (unit == 'char') { - var sel = this.ace.selection; - sel.clearSelection(); - sel.moveCursorBy(0, increment); - } - }; - 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 += 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); - } else { - debugger; - } - }; - this.charCoords = function(pos, mode) { - if (mode == 'div' || !mode) { - var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); - return {left: sc.column, top: sc.row}; - }if (mode == 'local') { - var renderer = this.ace.renderer; - var sc = this.ace.session.documentToScreenPosition(pos.line, pos.ch); - var lh = renderer.layerConfig.lineHeight; - var cw = renderer.layerConfig.characterWidth; - var top = lh * sc.row; - return {left: sc.column * cw, top: top, bottom: top + lh}; - } - }; - this.coordsChar = function(pos, mode) { - var renderer = this.ace.renderer; - if (mode == 'local') { - var row = Math.max(0, Math.floor(pos.top / renderer.lineHeight)); - var col = Math.max(0, Math.floor(pos.left / renderer.characterWidth)); - var ch = renderer.session.screenToDocumentPosition(row, col); - return toCmPos(ch); - } else if (mode == 'div') { - throw "not implemented"; - } - }; - this.getSearchCursor = function(query, pos, caseFold) { - var caseSensitive = false; - var isRegexp = false; - if (query instanceof RegExp && !query.global) { - caseSensitive = !query.ignoreCase; - query = query.source; - isRegexp = true; - } - var search = new Search(); - if (pos.ch == undefined) pos.ch = Number.MAX_VALUE; - var acePos = {row: pos.line, column: pos.ch}; - var cm = this; - var last = null; - return { - findNext: function() { return this.find(false) }, - findPrevious: function() {return this.find(true) }, - find: function(back) { - search.setOptions({ - needle: query, - caseSensitive: caseSensitive, - wrap: false, - backwards: back, - regExp: isRegexp, - start: last || acePos - }); - var range = search.find(cm.ace.session); - if (range && range.isEmpty()) { - if (cm.getLine(range.start.row).length == range.start.column) { - search.$options.start = range; - range = search.find(cm.ace.session); - } - } - last = range; - return last; - }, - from: function() { return last && toCmPos(last.start) }, - to: function() { return last && toCmPos(last.end) }, - replace: function(text) { - if (last) { - last.end = cm.ace.session.doc.replace(last, text); - } - } - }; - }; - this.scrollTo = function(x, y) { - var renderer = this.ace.renderer; - var config = renderer.layerConfig; - var maxHeight = config.maxHeight; - maxHeight -= (renderer.$size.scrollerHeight - renderer.lineHeight) * renderer.$scrollPastEnd; - if (y != null) this.ace.session.setScrollTop(Math.max(0, Math.min(y, maxHeight))); - if (x != null) this.ace.session.setScrollLeft(Math.max(0, Math.min(x, config.width))); - }; - this.scrollInfo = function() { return 0; }; - this.scrollIntoView = function(pos, 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) { - return this.ace.session.getTextRange(new Range(s.line, s.ch, e.line, e.ch)); - }; - this.replaceRange = function(text, s, e) { - if (!e) e = s; - return this.ace.session.replace(new Range(s.line, s.ch, e.line, e.ch), text); - }; - this.replaceSelections = function(p) { - var sel = this.ace.selection; - if (this.ace.inVirtualSelectionMode) { - this.ace.session.replace(sel.getRange(), p[0] || ""); - return; - } - sel.inVirtualSelectionMode = true; - var ranges = sel.rangeList.ranges; - if (!ranges.length) ranges = [this.ace.multiSelect.getRange()]; - for (var i = ranges.length; i--;) - this.ace.session.replace(ranges[i], p[i] || ""); - sel.inVirtualSelectionMode = false; - }; - this.getSelection = function() { - return this.ace.getSelectedText(); - }; - this.getSelections = function() { - return this.listSelections().map(function(x) { - return this.getRange(x.anchor, x.head); - }, this); - }; - this.getInputField = function() { - return this.ace.textInput.getElement(); - }; - this.getWrapperElement = function() { - return this.ace.containter; - }; - var optMap = { - indentWithTabs: "useSoftTabs", - indentUnit: "tabSize", - firstLineNumber: "firstLineNumber" - }; - this.setOption = function(name, val) { - this.state[name] = val; - switch (name) { - case 'indentWithTabs': - name = optMap[name]; - val = !val; - break; - default: - name = optMap[name]; - } - if (name) - this.ace.setOption(name, val); - }; - this.getOption = function(name, val) { - var aceOpt = optMap[name]; - if (aceOpt) - val = this.ace.getOption(aceOpt); - switch (name) { - case 'indentWithTabs': - name = optMap[name]; - return !val; - } - return aceOpt ? val : this.state[name]; - }; - this.toggleOverwrite = function(on) { - this.state.overwrite = on; - return this.ace.setOverwrite(on); - }; - this.addOverlay = function(o) { - if (!this.$searchHighlight || !this.$searchHighlight.session) { - var highlight = new SearchHighlight(null, "ace_highlight-marker", "text"); - var marker = this.ace.session.addDynamicMarker(highlight); - highlight.id = marker.id; - highlight.session = this.ace.session; - highlight.destroy = function(o) { - highlight.session.off("change", highlight.updateOnChange); - highlight.session.off("changeEditor", highlight.destroy); - highlight.session.removeMarker(highlight.id); - highlight.session = null; - }; - highlight.updateOnChange = function(delta) { - var row = delta.start.row; - if (row == delta.end.row) highlight.cache[row] = undefined; - else highlight.cache.splice(row, highlight.cache.length); - }; - highlight.session.on("changeEditor", highlight.destroy); - highlight.session.on("change", highlight.updateOnChange); - } - var re = new RegExp(o.query.source, "gmi"); - this.$searchHighlight = o.highlight = highlight; - this.$searchHighlight.setRegexp(re); - this.ace.renderer.updateBackMarkers(); - }; - this.removeOverlay = function(o) { - if (this.$searchHighlight && this.$searchHighlight.session) { - this.$searchHighlight.destroy(); - } - }; - this.getScrollInfo = function() { - var renderer = this.ace.renderer; - var config = renderer.layerConfig; - return { - left: renderer.scrollLeft, - top: renderer.scrollTop, - height: config.maxHeight, - width: config.width, - clientHeight: config.height, - clientWidth: config.width - }; - }; - this.getValue = function() { - return this.ace.getValue(); - }; - this.setValue = function(v) { - return this.ace.setValue(v); - }; - this.getTokenTypeAt = function(pos) { - var token = this.ace.session.getTokenAt(pos.line, pos.ch); - return token && /comment|string/.test(token.type) ? "string" : ""; - }; - this.findMatchingBracket = function(pos) { - var m = this.ace.session.findMatchingBracket(toAcePos(pos)); - return {to: m && toCmPos(m)}; - }; - this.indentLine = function(line, method) { - if (method === true) - this.ace.session.indentRows(line, line, "\t"); - else if (method === false) - this.ace.session.outdentRows(new Range(line, 0, line, 0)); - }; - this.indexFromPos = function(pos) { - return this.ace.session.doc.positionToIndex(toAcePos(pos)); - }; - this.posFromIndex = function(index) { - return toCmPos(this.ace.session.doc.indexToPosition(index)); - }; - this.focus = function(index) { - return this.ace.focus(); - }; - this.blur = function(index) { - return this.ace.blur(); - }; - this.defaultTextHeight = function(index) { - return this.ace.renderer.layerConfig.lineHeight; - }; - this.scanForBracket = function(pos, dir, _, options) { - var re = options.bracketRegex.source; - if (dir == 1) { - var m = this.ace.session.$findClosingBracket(re.slice(1, 2), toAcePos(pos), /paren|text/); - } else { - var m = this.ace.session.$findOpeningBracket(re.slice(-2, -1), {row: pos.line, column: pos.ch + 1}, /paren|text/); - } - return m && {pos: toCmPos(m)}; - }; - 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}; - } - function toCmPos(acePos) { - return new Pos(acePos.row, acePos.column); - } - - var StringStream = CodeMirror.StringStream = function(string, tabSize) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - this.lastColumnPos = this.lastColumnValue = 0; - this.lineStart = 0; - }; - - StringStream.prototype = { - eol: function() {return this.pos >= this.string.length;}, - sol: function() {return this.pos == this.lineStart;}, - peek: function() {return this.string.charAt(this.pos) || undefined;}, - next: function() { - if (this.pos < this.string.length) - return this.string.charAt(this.pos++); +var startCommands = { + "i": { + command: coreCommands.start }, - eat: function(match) { - var ch = this.string.charAt(this.pos); - if (typeof match == "string") var ok = ch == match; - else var ok = ch && (match.test ? match.test(ch) : match(ch)); - if (ok) {++this.pos; return ch;} + "I": { + command: coreCommands.startBeginning }, - eatWhile: function(match) { - var start = this.pos; - while (this.eat(match)){} - return this.pos > start; + "a": { + command: coreCommands.append }, - eatSpace: function() { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; - return this.pos > start; + "A": { + command: coreCommands.appendEnd }, - skipToEnd: function() {this.pos = this.string.length;}, - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) {this.pos = found; return true;} + "ctrl-f": { + command: "gotopagedown" }, - backUp: function(n) {this.pos -= n;}, - column: function() { - throw "not implemented"; - }, - indentation: function() { - throw "not implemented"; - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; - var substr = this.string.substr(this.pos, pattern.length); - if (cased(substr) == cased(pattern)) { - if (consume !== false) this.pos += pattern.length; - return true; - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && match.index > 0) return null; - if (match && consume !== false) this.pos += match[0].length; - return match; - } - }, - current: function(){return this.string.slice(this.start, this.pos);}, - hideFirstChars: function(n, inner) { - this.lineStart += n; - try { return inner(); } - finally { this.lineStart -= n; } + "ctrl-b": { + command: "gotopageup" } - }; - -// todo replace with showCommandLine -CodeMirror.defineExtension = function(name, fn) { - CodeMirror.prototype[name] = fn; }; -dom.importCssString(".normal-mode .ace_cursor{\ - border: 1px solid red;\ - background-color: red;\ - opacity: 0.5;\ -}\ -.normal-mode .ace_hidden-cursors .ace_cursor{\ - background-color: transparent;\ -}\ -.ace_dialog {\ - position: absolute;\ - left: 0; right: 0;\ - background: white;\ - z-index: 15;\ - padding: .1em .8em;\ - overflow: hidden;\ - color: #333;\ -}\ -.ace_dialog-top {\ - border-bottom: 1px solid #eee;\ - top: 0;\ -}\ -.ace_dialog-bottom {\ - border-top: 1px solid #eee;\ - bottom: 0;\ -}\ -.ace_dialog input {\ - border: none;\ - outline: none;\ - background: transparent;\ - width: 20em;\ - color: inherit;\ - font-family: monospace;\ -}", "vimMode"); -(function() { - function closeNotification(cm, newVal) { - if (cm.state.currentNotificationClose) - cm.state.currentNotificationClose(); - cm.state.currentNotificationClose = newVal; - } - CodeMirror.defineExtension("openDialog", function(template, callback, options) { - if (this.virtualSelectionMode()) return; - if (!options) options = {}; - - closeNotification(this, null); - - var dialog = dialogDiv(this, template, options.bottom); - var closed = false, me = this; - function close(newVal) { - if (typeof newVal == 'string') { - inp.value = newVal; - } else { - if (closed) return; - closed = true; - dialog.parentNode.removeChild(dialog); - me.focus(); - - if (options.onClose) options.onClose(dialog); - } - } - - var inp = dialog.getElementsByTagName("input")[0], button; - if (inp) { - if (options.value) { - inp.value = options.value; - if (options.select !== false) inp.select(); - } - - if (options.onInput) - CodeMirror.on(inp, "input", function(e) { options.onInput(e, inp.value, close);}); - if (options.onKeyUp) - CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);}); - - CodeMirror.on(inp, "keydown", function(e) { - if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; } - if (e.keyCode == 27 || (options.closeOnEnter !== false && e.keyCode == 13)) { - inp.blur(); - CodeMirror.e_stop(e); - close(); - } - if (e.keyCode == 13) callback(inp.value); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(inp, "blur", close); - - inp.focus(); - } else if (button = dialog.getElementsByTagName("button")[0]) { - CodeMirror.on(button, "click", function() { - close(); - me.focus(); - }); - - if (options.closeOnBlur !== false) CodeMirror.on(button, "blur", close); - - button.focus(); - } - return close; - }); - - CodeMirror.defineExtension("openNotification", function(template, options) { - if (this.virtualSelectionMode()) return; - closeNotification(this, close); - var dialog = dialogDiv(this, template, options && options.bottom); - var closed = false, doneTimer; - var duration = options && typeof options.duration !== "undefined" ? options.duration : 5000; - - function close() { - if (closed) return; - closed = true; - clearTimeout(doneTimer); - dialog.parentNode.removeChild(dialog); - } - - CodeMirror.on(dialog, 'click', function(e) { - CodeMirror.e_preventDefault(e); - close(); - }); - - if (duration) - doneTimer = setTimeout(close, duration); - - return close; - }); -})(); - - - var defaultKeymap = [ - // Key to key mapping. This goes first to make it possible to override - // existing mappings. - { keys: '', type: 'keyToKey', toKeys: 'h' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, - { keys: '', type: 'keyToKey', toKeys: 'W' }, - { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'w' }, - { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, - { keys: 's', type: 'keyToKey', toKeys: 'xi', context: 'visual'}, - { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, - { keys: 'S', type: 'keyToKey', toKeys: 'dcc', context: 'visual' }, - { keys: '', type: 'keyToKey', toKeys: '0' }, - { keys: '', type: 'keyToKey', toKeys: '$' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, - // Motions - { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, - { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, - { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, - { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, - { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, - { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, - { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, - { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, - { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, - { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, - { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, - { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, - { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, - { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, - { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, - { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, - { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, - { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, - { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, - { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, - { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, - { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, - { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, - { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, - { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, - { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, - { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, - { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, - { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, - { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, - { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, - { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, - // the next two aren't motions but must come before more general motion declarations - { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, - { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, - { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, - { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, - { keys: '|', type: 'motion', motion: 'moveToColumn'}, - { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, - { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, - // Operators - { keys: 'd', type: 'operator', operator: 'delete' }, - { keys: 'y', type: 'operator', operator: 'yank' }, - { keys: 'c', type: 'operator', operator: 'change' }, - { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, - { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, - { keys: 'g~', type: 'operator', operator: 'changeCase' }, - { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, - { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, - { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, - { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, - // Operator-Motion dual commands - { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, - { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, - { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, - { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, - { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, - // Actions - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, - { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, - { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, - { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, - { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, - { keys: 'v', type: 'action', action: 'toggleVisualMode' }, - { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, - { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, - { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, - { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, - { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, - { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, - { keys: 'r', type: 'action', action: 'replace', isEdit: true }, - { keys: '@', type: 'action', action: 'replayMacro' }, - { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, - // Handle Replace-mode as a special case of insert mode. - { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, - { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, - { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, - { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, - { keys: '', type: 'action', action: 'redo' }, - { keys: 'm', type: 'action', action: 'setMark' }, - { keys: '"', type: 'action', action: 'setRegister' }, - { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, - { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, - { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, - { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '.', type: 'action', action: 'repeatLastEdit' }, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, - // Text object motions - { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, - { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, - // Search - { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, - { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, - { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, - { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, - // Ex command - { keys: ':', type: 'ex' } - ]; - - var Pos = CodeMirror.Pos; - - var Vim = function() { return vimApi; } //{ - function enterVimMode(cm) { - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - } - - function leaveVimMode(cm) { - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; - } - - function detachVimMap(cm, next) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!next || next.attach != attachVimMap) - leaveVimMode(cm, false); - } - function attachVimMap(cm, prev) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!prev || prev.attach != attachVimMap) - enterVimMode(cm); - } - - // Deprecated, simply setting the keymap works again. - CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { - if (val && cm.getOption("keyMap") != "vim") - cm.setOption("keyMap", "vim"); - else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) - cm.setOption("keyMap", "default"); - }); - - function cmKey(key, cm) { - if (!cm) { return undefined; } - var vimKey = cmKeyToVimKey(key); - if (!vimKey) { - return false; - } - var cmd = CodeMirror.Vim.findKey(cm, vimKey); - if (typeof cmd == 'function') { - CodeMirror.signal(cm, 'vim-keypress', vimKey); - } - return cmd; - } - - var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; - var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del'}; - function cmKeyToVimKey(key) { - if (key.charAt(0) == '\'') { - // Keypress character binding of format "'a'" - return key.charAt(1); - } - var pieces = key.split('-'); - if (/-$/.test(key)) { - // If the - key was typed, split will result in 2 extra empty strings - // in the array. Replace them with 1 '-'. - pieces.splice(-2, 2, '-'); - } - var lastPiece = pieces[pieces.length - 1]; - if (pieces.length == 1 && pieces[0].length == 1) { - // No-modifier bindings use literal character bindings above. Skip. - return false; - } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { - // Ignore Shift+char bindings as they should be handled by literal character. - return false; - } - var hasCharacter = false; - for (var i = 0; i < pieces.length; i++) { - var piece = pieces[i]; - if (piece in modifiers) { pieces[i] = modifiers[piece]; } - else { hasCharacter = true; } - if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } - } - if (!hasCharacter) { - // Vim does not support modifier only keys. - return false; - } - // TODO: Current bindings expect the character to be lower case, but - // it looks like vim key notation uses upper case. - if (isUpperCase(lastPiece)) { - pieces[pieces.length - 1] = lastPiece.toLowerCase(); - } - return '<' + pieces.join('-') + '>'; - } - - function getOnPasteFn(cm) { - var vim = cm.state.vim; - if (!vim.onPasteFn) { - vim.onPasteFn = function() { - if (!vim.insertMode) { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); - actions.enterInsertMode(cm, {}, vim); - } - }; - } - return vim.onPasteFn; - } - - var numberRegex = /[\d]/; - 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++) { - keys.push(String.fromCharCode(i)); - } - return keys; - } - var upperCaseAlphabet = makeKeyRange(65, 26); - var lowerCaseAlphabet = makeKeyRange(97, 26); - var numbers = makeKeyRange(48, 10); - var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); - var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); - - function isLine(cm, line) { - return line >= cm.firstLine() && line <= cm.lastLine(); - } - function isLowerCase(k) { - return (/^[a-z]$/).test(k); - } - function isMatchableSymbol(k) { - return '()[]{}'.indexOf(k) != -1; - } - function isNumber(k) { - return numberRegex.test(k); - } - function isUpperCase(k) { - return (/^[A-Z]$/).test(k); - } - function isWhiteSpaceString(k) { - return (/^\s*$/).test(k); - } - function inArray(val, arr) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == val) { - return true; - } - } - return false; - } - - var options = {}; - 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, - callback: callback - }; - 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, cfg) { - var option = options[name]; - cfg = cfg || {}; - var scope = cfg.scope; - if (!option) { - throw Error('Unknown option: ' + name); - } - if (option.type == 'boolean') { - if (value && value !== true) { - throw Error('Invalid argument: ' + name + '=' + value); - } else if (value !== false) { - // Boolean options are set to true if value is not defined. - value = true; - } - } - 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, cm, cfg) { - var option = options[name]; - cfg = cfg || {}; - var scope = cfg.scope; - if (!option) { - throw Error('Unknown option: ' + name); - } - 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; - var head = 0; - var tail = 0; - var buffer = new Array(size); - function add(cm, oldCur, newCur) { - var current = pointer % size; - var curMark = buffer[current]; - function useNextSlot(cursor) { - var next = ++pointer % size; - var trashMark = buffer[next]; - if (trashMark) { - trashMark.clear(); - } - buffer[next] = cm.setBookmark(cursor); - } - if (curMark) { - var markPos = curMark.find(); - // avoid recording redundant cursor position - if (markPos && !cursorEqual(markPos, oldCur)) { - useNextSlot(oldCur); - } - } else { - useNextSlot(oldCur); - } - useNextSlot(newCur); - head = pointer; - tail = pointer - size + 1; - if (tail < 0) { - tail = 0; - } - } - function move(cm, offset) { - pointer += offset; - if (pointer > head) { - pointer = head; - } else if (pointer < tail) { - pointer = tail; - } - var mark = buffer[(size + pointer) % size]; - // skip marks that are temporarily removed from text buffer - if (mark && !mark.find()) { - var inc = offset > 0 ? 1 : -1; - var newCur; - var oldCur = cm.getCursor(); - do { - pointer += inc; - mark = buffer[(size + pointer) % size]; - // skip marks that are the same as current position - if (mark && - (newCur = mark.find()) && - !cursorEqual(oldCur, newCur)) { - break; - } - } while (pointer < head && pointer > tail); - } - return mark; - } - return { - cachedCursor: undefined, //used for # and * jumps - add: add, - move: move - }; - }; - - // Returns an object to track the changes associated insert mode. It - // clones the object that is passed in, or creates an empty object one if - // none is provided. - var createInsertModeChanges = function(c) { - if (c) { - // Copy construction - return { - changes: c.changes, - expectCursorActivityForChange: c.expectCursorActivityForChange - }; - } - return { - // Change list - changes: [], - // Set to true on change, false on cursorActivity. - expectCursorActivityForChange: false - }; - }; - - function MacroModeState() { - this.latestRegister = undefined; - this.isPlaying = false; - this.isRecording = false; - this.replaySearchQueries = []; - this.onRecordingDone = undefined; - this.lastInsertModeChanges = createInsertModeChanges(); - } - MacroModeState.prototype = { - exitMacroRecordMode: function() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.onRecordingDone) { - macroModeState.onRecordingDone(); // close dialog - } - macroModeState.onRecordingDone = undefined; - macroModeState.isRecording = false; - }, - enterMacroRecordMode: function(cm, registerName) { - var register = - vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.clear(); - this.latestRegister = registerName; - if (cm.openDialog) { - this.onRecordingDone = cm.openDialog( - '(recording)['+registerName+']', null, {bottom:true}); - } - this.isRecording = true; - } - } - }; - - function maybeInitVimState(cm) { - if (!cm.state.vim) { - // Store instance state in the CodeMirror object. - cm.state.vim = { - inputState: new InputState(), - // Vim's input state that triggered the last edit, used to repeat - // motions and operators with '.'. - lastEditInputState: undefined, - // Vim's action command before the last edit, used to repeat actions - // with '.' and insert mode repeat. - lastEditActionCommand: undefined, - // When using jk for navigation, if you move from a longer line to a - // shorter line, the cursor may clip to the end of the shorter line. - // If j is pressed again and cursor goes to the next line, the - // cursor should go back to its horizontal position on the longer - // line if it can. This is to keep track of the horizontal position. - lastHPos: -1, - // Doing the same with screen-position for gj/gk - lastHSPos: -1, - // The last motion command run. Cleared if a non-motion command gets - // executed in between. - lastMotion: null, - marks: {}, - // Mark for rendering fake cursor for visual mode. - fakeCursor: null, - insertMode: false, - // Repeat count for changes made in insert mode, triggered by key - // sequences like 3,i. Only exists when insertMode is true. - insertModeRepeat: undefined, - visualMode: false, - // If we are in visual line mode. No effect if visualMode is false. - visualLine: false, - visualBlock: false, - lastSelection: null, - lastPastedText: null, - sel: {}, - // Buffer-local/window-local values of vim options. - options: {} - }; - } - return cm.state.vim; - } - var vimGlobalState; - function resetVimGlobalState() { - vimGlobalState = { - // The current search query. - searchQuery: null, - // Whether we are searching backwards. - searchIsReversed: false, - // Replace part of the last substituted pattern - lastSubstituteReplacePart: undefined, - jumpList: createCircularJumpList(), - macroModeState: new MacroModeState, - // Recording latest f, t, F or T motion command. - lastChararacterSearch: {increment:0, forward:true, selectedCharacter:''}, - registerController: new RegisterController({}), - // search history buffer - searchHistoryController: new HistoryController({}), - // ex Command history buffer - exCommandHistoryController : new HistoryController({}) - }; - for (var optionName in options) { - var option = options[optionName]; - option.value = option.defaultValue; - } - } - - var lastInsertModeKeyTimer; - var vimApi= { - buildKeyMap: function() { - // TODO: Convert keymap into dictionary format for fast lookup. - }, - // Testing hook, though it might be useful to expose the register - // controller anyways. - getRegisterController: function() { - return vimGlobalState.registerController; - }, - // Testing hook. - resetVimGlobalState_: resetVimGlobalState, - - // Testing hook. - getVimGlobalState_: function() { - return vimGlobalState; - }, - - // Testing hook. - maybeInitVimState_: maybeInitVimState, - - suppressErrorLogging: false, - - InsertModeKey: InsertModeKey, - map: function(lhs, rhs, ctx) { - // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs, ctx); - }, - unmap: function(lhs, ctx) { - // 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, - defineEx: function(name, prefix, func){ - if (name.indexOf(prefix) !== 0) { - throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); - } - exCommands[name]=func; - exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; - }, - handleKey: function (cm, key, origin) { - var command = this.findKey(cm, key, origin); - if (typeof command === 'function') { - return command(); - } - }, - /** - * This is the outermost function called by CodeMirror, after keys have - * been mapped to their Vim equivalents. - * - * Finds a command based on the key (and cached keys if there is a - * multi-key sequence). Returns `undefined` if no key is matched, a noop - * function if a partial match is found (multi-key), and a function to - * execute the bound command if a a key is matched. The function always - * returns true. - */ - findKey: function(cm, key, origin) { - var vim = maybeInitVimState(cm); - function handleMacroRecording() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); - clearInputState(cm); - return true; - } - if (origin != 'mapping') { - logKey(macroModeState, key); - } - } - } - function handleEsc() { - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); - } else if (vim.insertMode) { - exitInsertMode(cm); - } - return true; - } - } - function doKeyToKey(keys) { - // TODO: prevent infinite recursion. - var match; - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(keys); - key = match[0]; - keys = keys.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'mapping'); - } - } - - function handleKeyInsertMode() { - if (handleEsc()) { return true; } - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - var keysAreChars = key.length == 1; - var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - // Need to check all key substrings in insert mode. - while (keys.length > 1 && match.type != 'full') { - var keys = vim.inputState.keyBuffer = keys.slice(1); - var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - if (thisMatch.type != 'none') { match = thisMatch; } - } - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - lastInsertModeKeyTimer = window.setTimeout( - function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, - getOption('insertModeEscKeysTimeout')); - return !keysAreChars; - } - - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - if (keysAreChars) { - var here = cm.getCursor(); - cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); - } - clearInputState(cm); - return match.command; - } - - function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { return true; }; - - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - if (/^[1-9]\d*$/.test(keys)) { return true; } - - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (!keysMatcher) { clearInputState(cm); return false; } - var context = vim.visualMode ? 'visual' : - 'normal'; - var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { return true; } - - vim.inputState.keyBuffer = ''; - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (keysMatcher[1] && keysMatcher[1] != '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]); - } - return match.command; - } - - var command; - if (vim.insertMode) { command = handleKeyInsertMode(); } - else { command = handleKeyNonInsertMode(); } - if (command === false) { - return undefined; - } else if (command === true) { - // TODO: Look into using CodeMirror's multi-key handling. - // Return no-op since we are caching the key. Counts as handled, but - // don't want act on it just yet. - return function() {}; - } else { - return function() { - return cm.operation(function() { - cm.curOp.isVimOp = true; - try { - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - maybeInitVimState(cm); - if (!CodeMirror.Vim.suppressErrorLogging) { - console['log'](e); - } - throw e; - } - return true; - }); - }; - } - }, - 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. - function InputState() { - this.prefixRepeat = []; - this.motionRepeat = []; - - this.operator = null; - this.operatorArgs = null; - this.motion = null; - this.motionArgs = null; - this.keyBuffer = []; // For matching multi-key commands. - this.registerName = null; // Defaults to the unnamed register. - } - InputState.prototype.pushRepeatDigit = function(n) { - if (!this.operator) { - this.prefixRepeat = this.prefixRepeat.concat(n); - } else { - this.motionRepeat = this.motionRepeat.concat(n); - } - }; - InputState.prototype.getRepeat = function() { - var repeat = 0; - if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { - repeat = 1; - if (this.prefixRepeat.length > 0) { - repeat *= parseInt(this.prefixRepeat.join(''), 10); - } - if (this.motionRepeat.length > 0) { - repeat *= parseInt(this.motionRepeat.join(''), 10); - } - } - return repeat; - }; - - function clearInputState(cm, reason) { - cm.state.vim.inputState = new InputState(); - CodeMirror.signal(cm, 'vim-command-done', reason); - } - - /* - * Register stores information about copy and paste registers. Besides - * text, a register must store whether it is linewise (i.e., when it is - * pasted, should it insert itself into a new line, or should the text be - * inserted at the cursor position.) - */ - function Register(text, linewise, blockwise) { - this.clear(); - this.keyBuffer = [text || '']; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - } - Register.prototype = { - setText: function(text, linewise, blockwise) { - this.keyBuffer = [text || '']; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - }, - pushText: function(text, linewise) { - // if this register has ever been set to linewise, use linewise. - if (linewise) { - if (!this.linewise) { - this.keyBuffer.push('\n'); - } - this.linewise = true; - } - this.keyBuffer.push(text); - }, - pushInsertModeChanges: function(changes) { - this.insertModeChanges.push(createInsertModeChanges(changes)); - }, - pushSearchQuery: function(query) { - this.searchQueries.push(query); - }, - clear: function() { - this.keyBuffer = []; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = false; - }, - toString: function() { - return this.keyBuffer.join(''); - } - }; - - /* - * vim registers allow you to keep many independent copy and paste buffers. - * See http://usevim.com/2012/04/13/registers/ for an introduction. - * - * RegisterController keeps the state of all the registers. An initial - * state may be passed in. The unnamed register '"' will always be - * overridden. - */ - function RegisterController(registers) { - this.registers = registers; - this.unnamedRegister = registers['"'] = new Register(); - registers['.'] = new Register(); - registers[':'] = new Register(); - registers['/'] = new Register(); - } - RegisterController.prototype = { - pushText: function(registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(0) == '\n') { - text = text.slice(1) + '\n'; - } - if (linewise && text.charAt(text.length - 1) !== '\n'){ - text += '\n'; - } - // Lowercase and uppercase registers refer to the same register. - // Uppercase just means append. - var register = this.isValidRegister(registerName) ? - this.getRegister(registerName) : null; - // if no register/an invalid register was specified, things go to the - // default registers - if (!register) { - switch (operator) { - case 'yank': - // The 0 register contains the text from the most recent yank. - this.registers['0'] = new Register(text, linewise, blockwise); - break; - case 'delete': - case 'change': - if (text.indexOf('\n') == -1) { - // Delete less than 1 line. Update the small delete register. - this.registers['-'] = new Register(text, linewise); - } else { - // Shift down the contents of the numbered registers and put the - // deleted text into register 1. - this.shiftNumericRegisters_(); - this.registers['1'] = new Register(text, linewise); - } - break; - } - // Make sure the unnamed register is set to what just happened - this.unnamedRegister.setText(text, linewise, blockwise); - return; - } - - // If we've gotten to this point, we've actually specified a register - var append = isUpperCase(registerName); - if (append) { - register.pushText(text, linewise); - } else { - register.setText(text, linewise, blockwise); - } - // The unnamed register always has the same value as the last used - // register. - this.unnamedRegister.setText(register.toString(), linewise); - }, - // Gets the register named @name. If one of @name doesn't already exist, - // create it. If @name is invalid, return the unnamedRegister. - getRegister: function(name) { - if (!this.isValidRegister(name)) { - return this.unnamedRegister; - } - name = name.toLowerCase(); - if (!this.registers[name]) { - this.registers[name] = new Register(); - } - return this.registers[name]; - }, - isValidRegister: function(name) { - return name && inArray(name, validRegisters); - }, - shiftNumericRegisters_: function() { - for (var i = 9; i >= 2; i--) { - this.registers[i] = this.getRegister('' + (i - 1)); - } - } - }; - function HistoryController() { - this.historyBuffer = []; - this.iterator; - this.initialPrefix = null; - } - HistoryController.prototype = { - // the input argument here acts a user entered prefix for a small time - // until we start autocompletion in which case it is the autocompleted. - nextMatch: function (input, up) { - var historyBuffer = this.historyBuffer; - var dir = up ? -1 : 1; - if (this.initialPrefix === null) this.initialPrefix = input; - for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { - var element = historyBuffer[i]; - for (var j = 0; j <= element.length; j++) { - if (this.initialPrefix == element.substring(0, j)) { - this.iterator = i; - return element; - } - } - } - // should return the user input in case we reach the end of buffer. - if (i >= historyBuffer.length) { - this.iterator = historyBuffer.length; - return this.initialPrefix; - } - // return the last autocompleted query or exCommand as it is. - if (i < 0 ) return input; - }, - pushInput: function(input) { - var index = this.historyBuffer.indexOf(input); - if (index > -1) this.historyBuffer.splice(index, 1); - if (input.length) this.historyBuffer.push(input); - }, - reset: function() { - this.initialPrefix = null; - this.iterator = this.historyBuffer.length; - } - }; - var commandDispatcher = { - matchCommand: function(keys, keyMap, inputState, context) { - var matches = commandMatches(keys, keyMap, context, inputState); - if (!matches.full && !matches.partial) { - return {type: 'none'}; - } else if (!matches.full && matches.partial) { - return {type: 'partial'}; - } - - var bestMatch; - for (var i = 0; i < matches.full.length; i++) { - var match = matches.full[i]; - if (!bestMatch) { - bestMatch = match; - } - } - if (bestMatch.keys.slice(-11) == '') { - inputState.selectedCharacter = lastChar(keys); - } - return {type: 'full', command: bestMatch}; - }, - processCommand: function(cm, vim, command) { - vim.inputState.repeatOverride = command.repeatOverride; - switch (command.type) { - case 'motion': - this.processMotion(cm, vim, command); - break; - case 'operator': - this.processOperator(cm, vim, command); - break; - case 'operatorMotion': - this.processOperatorMotion(cm, vim, command); - break; - case 'action': - this.processAction(cm, vim, command); - break; - case 'search': - this.processSearch(cm, vim, command); - break; - case 'ex': - case 'keyToEx': - this.processEx(cm, vim, command); - break; - default: - break; - } - }, - processMotion: function(cm, vim, command) { - vim.inputState.motion = command.motion; - vim.inputState.motionArgs = copyArgs(command.motionArgs); - this.evalInput(cm, vim); - }, - processOperator: function(cm, vim, command) { - var inputState = vim.inputState; - if (inputState.operator) { - if (inputState.operator == command.operator) { - // Typing an operator twice like 'dd' makes the operator operate - // linewise - inputState.motion = 'expandToLine'; - inputState.motionArgs = { linewise: true }; - this.evalInput(cm, vim); - return; - } else { - // 2 different operators in a row doesn't make sense. - clearInputState(cm); - } - } - inputState.operator = command.operator; - inputState.operatorArgs = copyArgs(command.operatorArgs); - if (vim.visualMode) { - // Operating on a selection in visual mode. We don't need a motion. - this.evalInput(cm, vim); - } - }, - processOperatorMotion: function(cm, vim, command) { - var visualMode = vim.visualMode; - var operatorMotionArgs = copyArgs(command.operatorMotionArgs); - if (operatorMotionArgs) { - // Operator motions may have special behavior in visual mode. - if (visualMode && operatorMotionArgs.visualLine) { - vim.visualLine = true; - } - } - this.processOperator(cm, vim, command); - if (!visualMode) { - this.processMotion(cm, vim, command); - } - }, - processAction: function(cm, vim, command) { - var inputState = vim.inputState; - var repeat = inputState.getRepeat(); - var repeatIsExplicit = !!repeat; - var actionArgs = copyArgs(command.actionArgs) || {}; - if (inputState.selectedCharacter) { - actionArgs.selectedCharacter = inputState.selectedCharacter; - } - // Actions may or may not have motions and operators. Do these first. - if (command.operator) { - this.processOperator(cm, vim, command); - } - if (command.motion) { - this.processMotion(cm, vim, command); - } - if (command.motion || command.operator) { - this.evalInput(cm, vim); - } - actionArgs.repeat = repeat || 1; - actionArgs.repeatIsExplicit = repeatIsExplicit; - actionArgs.registerName = inputState.registerName; - clearInputState(cm); - vim.lastMotion = null; - if (command.isEdit) { - this.recordLastEdit(vim, inputState, command); - } - actions[command.action](cm, actionArgs, vim); - }, - processSearch: function(cm, vim, command) { - if (!cm.getSearchCursor) { - // Search depends on SearchCursor. - return; - } - var forward = command.searchArgs.forward; - var wholeWordOnly = command.searchArgs.wholeWordOnly; - getSearchState(cm).setReversed(!forward); - var promptPrefix = (forward) ? '/' : '?'; - var originalQuery = getSearchState(cm).getQuery(); - var originalScrollPos = cm.getScrollInfo(); - function handleQuery(query, ignoreCase, smartCase) { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - try { - updateSearchQuery(cm, query, ignoreCase, smartCase); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + query); - clearInputState(cm); - return; - } - commandDispatcher.processMotion(cm, vim, { - type: 'motion', - motion: 'findNext', - motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } - }); - } - function onPromptClose(query) { - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - handleQuery(query, true /** ignoreCase */, true /** smartCase */); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - logSearchQuery(macroModeState, query); - } - } - function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; - close(query); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.searchHistoryController.reset(); - } - var parsedQuery; - try { - parsedQuery = updateSearchQuery(cm, query, - true /** ignoreCase */, true /** smartCase */); - } catch (e) { - // Swallow bad regexes for incremental search. - } - if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); - } else { - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - } - } - function onPromptKeyDown(e, query, close) { - var keyName = CodeMirror.keyName(e); - 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) { - case 'prompt': - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - var query = macroModeState.replaySearchQueries.shift(); - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: promptPrefix, - desc: searchPromptDesc, - onKeyUp: onPromptKeyUp, - onKeyDown: onPromptKeyDown - }); - } - break; - case 'wordUnderCursor': - var word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - true /** noSymbol */); - var isKeyword = true; - if (!word) { - word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - false /** noSymbol */); - isKeyword = false; - } - if (!word) { - return; - } - var query = cm.getLine(word.start.line).substring(word.start.ch, - word.end.ch); - if (isKeyword && wholeWordOnly) { - query = '\\b' + query + '\\b'; - } else { - query = escapeRegex(query); - } - - // cachedCursor is used to save the old position of the cursor - // when * or # causes vim to seek for the nearest word and shift - // the cursor before entering the motion. - vimGlobalState.jumpList.cachedCursor = cm.getCursor(); - cm.setCursor(word.start); - - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - break; - } - }, - processEx: function(cm, vim, command) { - function onPromptClose(input) { - // Give the prompt some time to close so that if processCommand shows - // an error, the elements don't overlap. - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - exCommandDispatcher.processCommand(cm, input); - } - function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), up; - 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(); - } - if (keyName == 'Up' || keyName == 'Down') { - 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(); - } - } - if (command.type == 'keyToEx') { - // Handle user defined Ex to Ex mappings - exCommandDispatcher.processCommand(cm, command.exArgs.input); - } else { - if (vim.visualMode) { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', - onKeyDown: onPromptKeyDown, select: false}); - } else { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', - onKeyDown: onPromptKeyDown}); - } - } - }, - evalInput: function(cm, vim) { - // If the motion comand is set, execute both the operator and motion. - // Otherwise return. - var inputState = vim.inputState; - var motion = inputState.motion; - var motionArgs = inputState.motionArgs || {}; - var operator = inputState.operator; - var operatorArgs = inputState.operatorArgs || {}; - 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 ? 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; - var repeat; - if (operator) { - this.recordLastEdit(vim, inputState); - } - if (inputState.repeatOverride !== undefined) { - // If repeatOverride is specified, that takes precedence over the - // input state's repeat. Used by Ex mode and can be user defined. - repeat = inputState.repeatOverride; - } else { - repeat = inputState.getRepeat(); - } - if (repeat > 0 && motionArgs.explicitRepeat) { - motionArgs.repeatIsExplicit = true; - } else if (motionArgs.noRepeat || - (!motionArgs.explicitRepeat && repeat === 0)) { - repeat = 1; - motionArgs.repeatIsExplicit = false; - } - if (inputState.selectedCharacter) { - // If there is a character input, stick it in all of the arg arrays. - motionArgs.selectedCharacter = operatorArgs.selectedCharacter = - inputState.selectedCharacter; - } - motionArgs.repeat = repeat; - clearInputState(cm); - if (motion) { - var motionResult = motions[motion](cm, origHead, motionArgs, vim); - vim.lastMotion = motions[motion]; - if (!motionResult) { - 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; - if (cachedCursor) { - recordJumpPosition(cm, cachedCursor, motionResult); - delete jumpList.cachedCursor; - } else { - recordJumpPosition(cm, origHead, motionResult); - } - } - if (motionResult instanceof Array) { - newAnchor = motionResult[0]; - newHead = motionResult[1]; - } else { - newHead = motionResult; - } - // TODO: Handle null returns from motion commands better. - if (!newHead) { - newHead = copyCursor(origHead); - } - if (vim.visualMode) { - if (!(vim.visualBlock && newHead.ch === Infinity)) { - newHead = clipCursorToContent(cm, newHead, vim.visualBlock); - } - if (newAnchor) { - newAnchor = clipCursorToContent(cm, newAnchor, true); - } - newAnchor = newAnchor || oldAnchor; - sel.anchor = newAnchor; - sel.head = newHead; - updateCmSelection(cm); - updateMark(cm, vim, '<', - cursorIsBefore(newAnchor, newHead) ? newAnchor - : newHead); - updateMark(cm, vim, '>', - cursorIsBefore(newAnchor, newHead) ? newHead - : newAnchor); - } else if (!operator) { - newHead = clipCursorToContent(cm, newHead); - cm.setCursor(newHead.line, newHead.ch); - } - } - if (operator) { - if (operatorArgs.lastSel) { - // Replaying a visual mode operation - newAnchor = oldAnchor; - var lastSel = operatorArgs.lastSel; - var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); - var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); - if (lastSel.visualLine) { - // Linewise Visual mode: The same number of lines. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } else if (lastSel.visualBlock) { - // Blockwise Visual mode: The same number of lines and columns. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); - } else if (lastSel.head.line == lastSel.anchor.line) { - // Normal Visual mode within one line: The same number of characters. - newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); - } else { - // Normal Visual mode with several lines: The same number of lines, in the - // last line the same number of characters as in the last line the last time. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } - vim.visualMode = true; - vim.visualLine = lastSel.visualLine; - vim.visualBlock = lastSel.visualBlock; - sel = vim.sel = { - anchor: newAnchor, - head: newHead - }; - updateCmSelection(cm); - } else if (vim.visualMode) { - operatorArgs.lastSel = { - anchor: copyCursor(sel.anchor), - head: copyCursor(sel.head), - visualBlock: vim.visualBlock, - visualLine: vim.visualLine - }; - } - var curStart, curEnd, linewise, mode; - var cmSel; - if (vim.visualMode) { - // Init visual op - curStart = cursorMin(sel.head, sel.anchor); - curEnd = cursorMax(sel.head, sel.anchor); - linewise = vim.visualLine || operatorArgs.linewise; - mode = vim.visualBlock ? 'block' : - linewise ? 'line' : - 'char'; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode); - if (linewise) { - var ranges = cmSel.ranges; - if (mode == 'block') { - // Linewise operators in visual block mode extend to end of line - for (var i = 0; i < ranges.length; i++) { - ranges[i].head.ch = lineLength(cm, ranges[i].head.line); - } - } else if (mode == 'line') { - ranges[0].head = Pos(ranges[0].head.line + 1, 0); - } - } - } else { - // Init motion op - curStart = copyCursor(newAnchor || oldAnchor); - curEnd = copyCursor(newHead || oldHead); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - } - linewise = motionArgs.linewise || operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); - } - mode = 'char'; - var exclusive = !motionArgs.inclusive || linewise; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode, exclusive); - } - cm.setSelections(cmSel.ranges, cmSel.primary); - vim.lastMotion = null; - operatorArgs.repeat = repeat; // For indent in visual mode. - operatorArgs.registerName = registerName; - // Keep track of linewise as it affects how paste and change behave. - operatorArgs.linewise = linewise; - var operatorMoveTo = operators[operator]( - cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); - if (vim.visualMode) { - exitVisualMode(cm, operatorMoveTo != null); - } - if (operatorMoveTo) { - cm.setCursor(operatorMoveTo); - } - } - }, - recordLastEdit: function(vim, inputState, actionCommand) { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - vim.lastEditInputState = inputState; - vim.lastEditActionCommand = actionCommand; - macroModeState.lastInsertModeChanges.changes = []; - macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; - } - }; - - /** - * typedef {Object{line:number,ch:number}} Cursor An object containing the - * position of the cursor. - */ - // All of the functions below return Cursor objects. - var motions = { - moveToTopLine: function(cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToMiddleLine: function(cm) { - var range = getUserVisibleLines(cm); - var line = Math.floor((range.top + range.bottom) * 0.5); - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToBottomLine: function(cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - expandToLine: function(_cm, head, motionArgs) { - // Expands forward to end of line, and then to next line if repeat is - // >1. Does not handle backward motion! - var cur = head; - return Pos(cur.line + motionArgs.repeat - 1, Infinity); - }, - findNext: function(cm, _head, motionArgs) { - var state = getSearchState(cm); - var query = state.getQuery(); - if (!query) { - return; - } - var prev = !motionArgs.forward; - // If search is initiated with ? instead of /, negate direction. - prev = (state.isReversed()) ? !prev : prev; - highlightSearchMatches(cm, query); - return findNext(cm, prev/** prev */, query, motionArgs.repeat); - }, - goToMark: function(cm, _head, motionArgs, vim) { - var mark = vim.marks[motionArgs.selectedCharacter]; - if (mark) { - var pos = mark.find(); - return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; - } - return null; - }, - moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { - if (vim.visualBlock && motionArgs.sameLine) { - var sel = vim.sel; - return [ - clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), - clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) - ]; - } else { - return ([vim.sel.head, vim.sel.anchor]); - } - }, - jumpToMark: function(cm, head, motionArgs, vim) { - var best = head; - for (var i = 0; i < motionArgs.repeat; i++) { - var cursor = best; - for (var key in vim.marks) { - if (!isLowerCase(key)) { - continue; - } - var mark = vim.marks[key].find(); - var isWrongDirection = (motionArgs.forward) ? - cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); - - if (isWrongDirection) { - continue; - } - if (motionArgs.linewise && (mark.line == cursor.line)) { - continue; - } - - var equal = cursorEqual(cursor, best); - var between = (motionArgs.forward) ? - cursorIsBetween(cursor, mark, best) : - cursorIsBetween(best, mark, cursor); - - if (equal || between) { - best = mark; - } - } - } - - if (motionArgs.linewise) { - // Vim places the cursor on the first non-whitespace character of - // the line if there is one, else it places the cursor at the end - // of the line, regardless of whether a mark was found. - best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); - } - return best; - }, - moveByCharacters: function(_cm, head, motionArgs) { - var cur = head; - var repeat = motionArgs.repeat; - var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; - return Pos(cur.line, ch); - }, - moveByLines: function(cm, head, motionArgs, vim) { - var cur = head; - var endCh = cur.ch; - // Depending what our last motion was, we may want to do different - // things. If our last motion was moving vertically, we want to - // preserve the HPos from our last horizontal move. If our last motion - // was going to the end of a line, moving vertically we should go to - // the end of the line, etc. - switch (vim.lastMotion) { - case this.moveByLines: - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveToColumn: - case this.moveToEol: - endCh = vim.lastHPos; - break; - default: - vim.lastHPos = endCh; - } - var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); - var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; - var first = cm.firstLine(); - var last = cm.lastLine(); - // Vim cancels linewise motions that start on an edge and move beyond - // that edge. It does not cancel motions that do not start on an edge. - if ((line < first && cur.line == first) || - (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; - } - vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; - return Pos(line, endCh); - }, - moveByDisplayLines: function(cm, head, motionArgs, vim) { - var cur = head; - switch (vim.lastMotion) { - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveByLines: - case this.moveToColumn: - case this.moveToEol: - break; - default: - vim.lastHSPos = cm.charCoords(cur,'div').left; - } - var repeat = motionArgs.repeat; - var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); - if (res.hitSide) { - if (motionArgs.forward) { - var lastCharCoords = cm.charCoords(res, 'div'); - var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; - var res = cm.coordsChar(goalCoords, 'div'); - } else { - var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); - resCoords.left = vim.lastHSPos; - res = cm.coordsChar(resCoords, 'div'); - } - } - vim.lastHPos = res.ch; - return res; - }, - moveByPage: function(cm, head, motionArgs) { - // CodeMirror only exposes functions that move the cursor page down, so - // doing this bad hack to move the cursor and move it back. evalInput - // will move the cursor to where it should be in the end. - var curStart = head; - var repeat = motionArgs.repeat; - return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); - }, - moveByParagraph: function(cm, head, motionArgs) { - var dir = motionArgs.forward ? 1 : -1; - return findParagraph(cm, head, motionArgs.repeat, dir); - }, - moveByScroll: function(cm, head, motionArgs, vim) { - var scrollbox = cm.getScrollInfo(); - var curEnd = null; - var repeat = motionArgs.repeat; - if (!repeat) { - repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); - } - var orig = cm.charCoords(head, 'local'); - motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); - if (!curEnd) { - return null; - } - var dest = cm.charCoords(curEnd, 'local'); - cm.scrollTo(null, scrollbox.top + dest.top - orig.top); - return curEnd; - }, - moveByWords: function(cm, head, motionArgs) { - return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, - !!motionArgs.wordEnd, !!motionArgs.bigWord); - }, - moveTillCharacter: function(cm, _head, motionArgs) { - var repeat = motionArgs.repeat; - var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter); - var increment = motionArgs.forward ? -1 : 1; - recordLastCharacterSearch(increment, motionArgs); - if (!curEnd) return null; - curEnd.ch += increment; - return curEnd; - }, - moveToCharacter: function(cm, head, motionArgs) { - var repeat = motionArgs.repeat; - recordLastCharacterSearch(0, motionArgs); - return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || head; - }, - moveToSymbol: function(cm, head, motionArgs) { - var repeat = motionArgs.repeat; - return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || head; - }, - moveToColumn: function(cm, head, motionArgs, vim) { - var repeat = motionArgs.repeat; - // repeat is equivalent to which column we want to move to! - vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(head,'div').left; - return moveToColumn(cm, repeat); - }, - moveToEol: function(cm, head, motionArgs, vim) { - var cur = head; - vim.lastHPos = Infinity; - var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); - var end=cm.clipPos(retval); - end.ch--; - vim.lastHSPos = cm.charCoords(end,'div').left; - return retval; - }, - moveToFirstNonWhiteSpaceCharacter: function(cm, head) { - // Go to the start of the line where the text begins, or the end for - // whitespace-only lines - var cursor = head; - return Pos(cursor.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); - }, - moveToMatchedSymbol: function(cm, head) { - var cursor = head; - var line = cursor.line; - var ch = cursor.ch; - var lineText = cm.getLine(line); - var symbol; - do { - symbol = lineText.charAt(ch++); - if (symbol && isMatchableSymbol(symbol)) { - var style = cm.getTokenTypeAt(Pos(line, ch)); - if (style !== "string" && style !== "comment") { - break; - } - } - } while (symbol); - if (symbol) { - var matched = cm.findMatchingBracket(Pos(line, ch)); - return matched.to; - } else { - return cursor; - } - }, - moveToStartOfLine: function(_cm, head) { - return Pos(head.line, 0); - }, - moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { - var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); - if (motionArgs.repeatIsExplicit) { - lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); - } - return Pos(lineNum, - findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); - }, - textObjectManipulation: function(cm, head, motionArgs, vim) { - // TODO: lots of possible exceptions that can be thrown here. Try da( - // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators - var mirroredPairs = {'(': ')', ')': '(', - '{': '}', '}': '{', - '[': ']', ']': '['}; - var selfPaired = {'\'': true, '"': true}; - - var character = motionArgs.selectedCharacter; - // 'b' refers to '()' block. - // 'B' refers to '{}' block. - if (character == 'b') { - character = '('; - } else if (character == 'B') { - character = '{'; - } - - // Inclusive is the difference between a and i - // TODO: Instead of using the additional text object map to perform text - // object operations, merge the map into the defaultKeyMap and use - // motionArgs to define behavior. Define separate entries for 'aw', - // 'iw', 'a[', 'i[', etc. - var inclusive = !motionArgs.textObjectInner; - - var tmp; - if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, head, character, inclusive); - } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, head, character, inclusive); - } else if (character === 'W') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - true /** bigWord */); - } else if (character === 'w') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - false /** bigWord */); - } else if (character === 'p') { - tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); - motionArgs.linewise = true; - if (vim.visualMode) { - if (!vim.visualLine) { vim.visualLine = true; } - } else { - var operatorArgs = vim.inputState.operatorArgs; - if (operatorArgs) { operatorArgs.linewise = true; } - tmp.end.line--; - } - } else { - // No text object defined for this, don't move. - return null; - } - - if (!cm.state.vim.visualMode) { - return [tmp.start, tmp.end]; - } else { - return expandSelection(cm, tmp.start, tmp.end); - } - }, - - repeatLastCharacterSearch: function(cm, head, motionArgs) { - var lastSearch = vimGlobalState.lastChararacterSearch; - var repeat = motionArgs.repeat; - var forward = motionArgs.forward === lastSearch.forward; - var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); - cm.moveH(-increment, 'char'); - motionArgs.inclusive = forward ? true : false; - var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); - if (!curEnd) { - cm.moveH(increment, 'char'); - return head; - } - curEnd.ch += increment; - return curEnd; - } - }; - - function defineMotion(name, fn) { - motions[name] = fn; - } - - function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; - } - /** - * An operator acts on a text selection. It receives the list of selections - * as input. The corresponding CodeMirror selection is guaranteed to - * match the input selection. - */ - var operators = { - change: function(cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; - if (!vim.visualMode) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - text = cm.getRange(anchor, head); - 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 && lastState.motionArgs && lastState.motionArgs.forward) { - head = offsetCursor(head, 0, - match[0].length); - text = text.slice(0, - match[0].length); - } - } - var wasLastLine = head.line - 1 == cm.lastLine(); - cm.replaceRange('', anchor, head); - if (args.linewise && !wasLastLine) { - // Push the next line back down, if there is a next line. - CodeMirror.commands.newlineAndIndent(cm); - // null ch so setCursor moves to end of line. - anchor.ch = null; - } - finalHead = anchor; - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = cursorMin(ranges[0].head, ranges[0].anchor); - } - vimGlobalState.registerController.pushText( - args.registerName, 'change', text, - args.linewise, ranges.length > 1); - actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); - }, - // delete is a javascript keyword. - 'delete': function(cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - if (!vim.visualBlock) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - if (args.linewise && - head.line != cm.firstLine() && - anchor.line == cm.lastLine() && - anchor.line == head.line - 1) { - // Special case for dd on last line (and first line). - if (anchor.line == cm.firstLine()) { - anchor.ch = 0; - } else { - anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); - } - } - text = cm.getRange(anchor, head); - cm.replaceRange('', anchor, head); - finalHead = anchor; - if (args.linewise) { - finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); - } - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = ranges[0].anchor; - } - vimGlobalState.registerController.pushText( - args.registerName, 'delete', text, - args.linewise, vim.visualBlock); - return clipCursorToContent(cm, finalHead); - }, - indent: function(cm, args, ranges) { - var vim = cm.state.vim; - var startLine = ranges[0].anchor.line; - var endLine = vim.visualBlock ? - ranges[ranges.length - 1].anchor.line : - ranges[0].head.line; - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = (vim.visualMode) ? args.repeat : 1; - if (args.linewise) { - // The only way to delete a newline is to delete until the start of - // the next line, so in linewise mode evalInput will include the next - // line. We don't want this in indent, so we go back a line. - endLine--; - } - for (var i = startLine; i <= endLine; i++) { - for (var j = 0; j < repeat; j++) { - cm.indentLine(i, args.indentRight); - } - } - return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); - }, - changeCase: function(cm, args, ranges, oldAnchor, newHead) { - var selections = cm.getSelections(); - var swapped = []; - var toLower = args.toLower; - for (var j = 0; j < selections.length; j++) { - var toSwap = selections[j]; - var text = ''; - if (toLower === true) { - text = toSwap.toLowerCase(); - } else if (toLower === false) { - text = toSwap.toUpperCase(); - } else { - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : - character.toUpperCase(); - } - } - swapped.push(text); - } - cm.replaceSelections(swapped); - if (args.shouldMoveCursor){ - return newHead; - } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { - return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); - } else if (args.linewise){ - return oldAnchor; - } else { - return cursorMin(ranges[0].anchor, ranges[0].head); - } - }, - yank: function(cm, args, ranges, oldAnchor) { - var vim = cm.state.vim; - var text = cm.getSelection(); - var endPos = vim.visualMode - ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) - : oldAnchor; - vimGlobalState.registerController.pushText( - args.registerName, 'yank', - text, args.linewise, vim.visualBlock); - return endPos; - } - }; - - function defineOperator(name, fn) { - operators[name] = fn; - } - - var actions = { - jumpListWalk: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat; - var forward = actionArgs.forward; - var jumpList = vimGlobalState.jumpList; - - var mark = jumpList.move(cm, forward ? repeat : -repeat); - 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) { - return; - } - var repeat = actionArgs.repeat || 1; - var lineHeight = cm.defaultTextHeight(); - var top = cm.getScrollInfo().top; - var delta = lineHeight * repeat; - var newPos = actionArgs.forward ? top + delta : top - delta; - var cursor = copyCursor(cm.getCursor()); - var cursorCoords = cm.charCoords(cursor, 'local'); - if (actionArgs.forward) { - if (newPos > cursorCoords.top) { - cursor.line += (newPos - cursorCoords.top) / lineHeight; - cursor.line = Math.ceil(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo(null, cursorCoords.top); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } else { - var newBottom = newPos + cm.getScrollInfo().clientHeight; - if (newBottom < cursorCoords.bottom) { - cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; - cursor.line = Math.floor(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo( - null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } - }, - scrollToCursor: function(cm, actionArgs) { - var lineNum = cm.getCursor().line; - var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); - var height = cm.getScrollInfo().clientHeight; - var y = charCoords.top; - var lineHeight = charCoords.bottom - y; - switch (actionArgs.position) { - case 'center': y = y - (height / 2) + lineHeight; - break; - case 'bottom': y = y - height + lineHeight*1.4; - break; - case 'top': y = y + lineHeight*0.4; - break; - } - cm.scrollTo(null, y); - }, - replayMacro: function(cm, actionArgs, vim) { - var registerName = actionArgs.selectedCharacter; - var repeat = actionArgs.repeat; - var macroModeState = vimGlobalState.macroModeState; - if (registerName == '@') { - registerName = macroModeState.latestRegister; - } - while(repeat--){ - executeMacroRegister(cm, vim, macroModeState, registerName); - } - }, - enterMacroRecordMode: function(cm, actionArgs) { - var macroModeState = vimGlobalState.macroModeState; - var registerName = actionArgs.selectedCharacter; - macroModeState.enterMacroRecordMode(cm, registerName); - }, - enterInsertMode: function(cm, actionArgs, vim) { - if (cm.getOption('readOnly')) { return; } - vim.insertMode = true; - vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; - var insertAt = (actionArgs) ? actionArgs.insertAt : null; - var sel = vim.sel; - var head = actionArgs.head || cm.getCursor('head'); - var height = cm.listSelections().length; - if (insertAt == 'eol') { - head = Pos(head.line, lineLength(cm, head.line)); - } else if (insertAt == 'charAfter') { - head = offsetCursor(head, 0, 1); - } else if (insertAt == 'firstNonBlank') { - head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); - } else if (insertAt == 'startOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line < sel.anchor.line) { - head = sel.head; - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.min(sel.head.ch, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'endOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line >= sel.anchor.line) { - head = offsetCursor(sel.head, 0, 1); - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.max(sel.head.ch + 1, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'inplace') { - if (vim.visualMode){ - return; - } - } - cm.setOption('keyMap', 'vim-insert'); - cm.setOption('disableInput', false); - if (actionArgs && actionArgs.replace) { - // Handle Replace-mode as a special case of insert mode. - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); - } else { - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); - } - if (!vimGlobalState.macroModeState.isPlaying) { - // Only record if not replaying. - cm.on('change', onChange); - CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (vim.visualMode) { - exitVisualMode(cm); - } - selectForInsert(cm, head, height); - }, - toggleVisualMode: function(cm, actionArgs, vim) { - var repeat = actionArgs.repeat; - var anchor = cm.getCursor(); - var head; - // TODO: The repeat should actually select number of characters/lines - // equal to the repeat times the size of the previous visual - // operation. - if (!vim.visualMode) { - // Entering visual mode - vim.visualMode = true; - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - head = clipCursorToContent( - cm, Pos(anchor.line, anchor.ch + repeat - 1), - true /** includeLineBreak */); - vim.sel = { - anchor: anchor, - head: head - }; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - } else if (vim.visualLine ^ actionArgs.linewise || - vim.visualBlock ^ actionArgs.blockwise) { - // Toggling between modes - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); - updateCmSelection(cm); - } else { - exitVisualMode(cm); - } - }, - reselectLastSelection: function(cm, _actionArgs, vim) { - var lastSelection = vim.lastSelection; - if (vim.visualMode) { - updateLastSelection(cm, vim); - } - if (lastSelection) { - var anchor = lastSelection.anchorMark.find(); - var head = lastSelection.headMark.find(); - if (!anchor || !head) { - // If the marks have been destroyed due to edits, do nothing. - return; - } - vim.sel = { - anchor: anchor, - head: head - }; - vim.visualMode = true; - vim.visualLine = lastSelection.visualLine; - vim.visualBlock = lastSelection.visualBlock; - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine ? 'linewise' : - vim.visualBlock ? 'blockwise' : ''}); - } - }, - joinLines: function(cm, actionArgs, vim) { - var curStart, curEnd; - 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. - var repeat = Math.max(actionArgs.repeat, 2); - curStart = cm.getCursor(); - curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, - Infinity)); - } - var finalCh = 0; - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curFinalPos); - }, - newLineAndEnterInsertMode: function(cm, actionArgs, vim) { - vim.insertMode = true; - var insertAt = copyCursor(cm.getCursor()); - if (insertAt.line === cm.firstLine() && !actionArgs.after) { - // Special case for inserting newline before start of document. - cm.replaceRange('\n', Pos(cm.firstLine(), 0)); - cm.setCursor(cm.firstLine(), 0); - } else { - insertAt.line = (actionArgs.after) ? insertAt.line : - insertAt.line - 1; - insertAt.ch = lineLength(cm, insertAt.line); - cm.setCursor(insertAt); - var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - newlineFn(cm); - } - this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); - }, - paste: function(cm, actionArgs, vim) { - var cur = copyCursor(cm.getCursor()); - var register = vimGlobalState.registerController.getRegister( - actionArgs.registerName); - var text = register.toString(); - if (!text) { - return; - } - if (actionArgs.matchIndent) { - var tabSize = cm.getOption("tabSize"); - // length that considers tabs and tabSize - var whitespaceLength = function(str) { - var tabs = (str.split("\t").length - 1); - var spaces = (str.split(" ").length - 1); - return tabs * tabSize + spaces * 1; - }; - var currentLine = cm.getLine(cm.getCursor().line); - var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); - // chomp last newline b/c don't want it to match /^\s*/gm - var chompedText = text.replace(/\n$/, ''); - var wasChomped = text !== chompedText; - var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); - var text = chompedText.replace(/^\s*/gm, function(wspace) { - var newIndent = indent + (whitespaceLength(wspace) - firstIndent); - if (newIndent < 0) { - return ""; - } - else if (cm.getOption("indentWithTabs")) { - var quotient = Math.floor(newIndent / tabSize); - return Array(quotient + 1).join('\t'); - } - else { - return Array(newIndent + 1).join(' '); - } - }); - text += wasChomped ? "\n" : ""; - } - if (actionArgs.repeat > 1) { - var text = Array(actionArgs.repeat + 1).join(text); - } - var linewise = register.linewise; - var blockwise = register.blockwise; - if (linewise) { - if(vim.visualMode) { - text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; - } else if (actionArgs.after) { - // Move the newline at the end to the start instead, and paste just - // before the newline character of the line we are on right now. - text = '\n' + text.slice(0, text.length - 1); - cur.ch = lineLength(cm, cur.line); - } else { - cur.ch = 0; - } - } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = (text[i] == '') ? ' ' : text[i]; - } - } - cur.ch += actionArgs.after ? 1 : 0; - } - var curPosFinal; - var idx; - if (vim.visualMode) { - // save the pasted text for reselection if the need arises - vim.lastPastedText = text; - var lastSelectionCurEnd; - var selectedArea = getSelectedAreaRange(cm, vim); - var selectionStart = selectedArea[0]; - var selectionEnd = selectedArea[1]; - var selectedText = cm.getSelection(); - var selections = cm.listSelections(); - var emptyStrings = new Array(selections.length).join('1').split('1'); - // save the curEnd marker before it get cleared due to cm.replaceRange. - if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.headMark.find(); - } - // push the previously selected text to unnamed register - vimGlobalState.registerController.unnamedRegister.setText(selectedText); - if (blockwise) { - // first delete the selected text - cm.replaceSelections(emptyStrings); - // Set new selections as per the block length of the yanked text - selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - cm.replaceSelections(text); - curPosFinal = selectionStart; - } else if (vim.visualBlock) { - cm.replaceSelections(emptyStrings); - cm.setCursor(selectionStart); - cm.replaceRange(text, selectionStart, selectionStart); - curPosFinal = selectionStart; - } else { - cm.replaceRange(text, selectionStart, selectionEnd); - curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); - } - // restore the the curEnd marker - if(lastSelectionCurEnd) { - vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); - } - if (linewise) { - curPosFinal.ch=0; - } - } else { - if (blockwise) { - cm.setCursor(cur); - for (var i = 0; i < text.length; i++) { - var line = cur.line+i; - if (line > cm.lastLine()) { - cm.replaceRange('\n', Pos(line, 0)); - } - var lastCh = lineLength(cm, line); - if (lastCh < cur.ch) { - extendLineToColumn(cm, line, cur.ch); - } - } - cm.setCursor(cur); - selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); - cm.replaceSelections(text); - curPosFinal = cur; - } else { - cm.replaceRange(text, cur); - // Now fine tune the cursor to where we want it. - if (linewise && actionArgs.after) { - curPosFinal = Pos( - cur.line + 1, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos( - cur.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length - 1); - } else { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length); - } - } - } - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curPosFinal); - }, - undo: function(cm, actionArgs) { - cm.operation(function() { - repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); - cm.setCursor(cm.getCursor('anchor')); - }); - }, - redo: function(cm, actionArgs) { - repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); - }, - setRegister: function(_cm, actionArgs, vim) { - vim.inputState.registerName = actionArgs.selectedCharacter; - }, - setMark: function(cm, actionArgs, vim) { - var markName = actionArgs.selectedCharacter; - updateMark(cm, vim, markName, cm.getCursor()); - }, - replace: function(cm, actionArgs, vim) { - var replaceWith = actionArgs.selectedCharacter; - var curStart = cm.getCursor(); - var replaceTo; - var curEnd; - var selections = cm.listSelections(); - if (vim.visualMode) { - curStart = cm.getCursor('start'); - curEnd = cm.getCursor('end'); - } else { - var line = cm.getLine(curStart.line); - replaceTo = curStart.ch + actionArgs.repeat; - if (replaceTo > line.length) { - replaceTo=line.length; - } - curEnd = Pos(curStart.line, replaceTo); - } - if (replaceWith=='\n') { - if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); - // special case, where vim help says to replace by just one line-break - (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); - } else { - var replaceWithStr = cm.getRange(curStart, curEnd); - //replace all characters in range by selected, but keep linebreaks - replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); - if (vim.visualBlock) { - // Tabs are split in visua block before replacing - var spaces = new Array(cm.getOption("tabSize")+1).join(' '); - replaceWithStr = cm.getSelection(); - replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); - cm.replaceSelections(replaceWithStr); - } else { - cm.replaceRange(replaceWithStr, curStart, curEnd); - } - if (vim.visualMode) { - curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? - selections[0].anchor : selections[0].head; - cm.setCursor(curStart); - exitVisualMode(cm, false); - } else { - cm.setCursor(offsetCursor(curEnd, 0, -1)); - } - } - }, - incrementNumberToken: function(cm, actionArgs) { - var cur = cm.getCursor(); - var lineStr = cm.getLine(cur.line); - var re = /-?\d+/g; - var match; - var start; - var end; - var numberStr; - var token; - while ((match = re.exec(lineStr)) !== null) { - token = match[0]; - start = match.index; - end = start + token.length; - if (cur.ch < end)break; - } - if (!actionArgs.backtrack && (end <= cur.ch))return; - if (token) { - var increment = actionArgs.increase ? 1 : -1; - var number = parseInt(token) + (increment * actionArgs.repeat); - var from = Pos(cur.line, start); - var to = Pos(cur.line, end); - numberStr = number.toString(); - cm.replaceRange(numberStr, from, to); - } else { - return; - } - cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); - }, - repeatLastEdit: function(cm, actionArgs, vim) { - var lastEditInputState = vim.lastEditInputState; - if (!lastEditInputState) { return; } - var repeat = actionArgs.repeat; - if (repeat && actionArgs.repeatIsExplicit) { - vim.lastEditInputState.repeatOverride = repeat; - } else { - repeat = vim.lastEditInputState.repeatOverride || repeat; - } - repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); - }, - exitInsertMode: exitInsertMode - }; - - function defineAction(name, fn) { - actions[name] = fn; - } - - /* - * Below are miscellaneous utility functions used by vim.js - */ - - /** - * Clips cursor to ensure that line is within the buffer's range - * If includeLineBreak is true, then allow cur.ch == lineLength. - */ - function clipCursorToContent(cm, cur, includeLineBreak) { - var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); - var maxCh = lineLength(cm, line) - 1; - maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; - var ch = Math.min(Math.max(0, cur.ch), maxCh); - return Pos(line, ch); - } - function copyArgs(args) { - var ret = {}; - for (var prop in args) { - if (args.hasOwnProperty(prop)) { - ret[prop] = args[prop]; - } - } - return ret; - } - function offsetCursor(cur, offsetLine, offsetCh) { - if (typeof offsetLine === 'object') { - offsetCh = offsetLine.ch; - offsetLine = offsetLine.line; - } - return Pos(cur.line + offsetLine, cur.ch + offsetCh); - } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - }; - } - function commandMatches(keys, keyMap, context, inputState) { - // Partial matches are not applied. They inform the key handler - // that the current key sequence is a subsequence of a valid key - // sequence, so that the key buffer is not cleared. - var match, partial = [], full = []; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (context == 'insert' && command.context != 'insert' || - command.context && command.context != context || - inputState.operator && command.type == 'action' || - !(match = commandMatch(keys, command.keys))) { continue; } - if (match == 'partial') { partial.push(command); } - if (match == 'full') { full.push(command); } - } - return { - partial: partial.length && partial, - full: full.length && full - }; - } - function commandMatch(pressed, mapped) { - if (mapped.slice(-11) == '') { - // Last character matches anything. - var prefixLen = mapped.length - 11; - var pressedPrefix = pressed.slice(0, prefixLen); - var mappedPrefix = mapped.slice(0, prefixLen); - return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : - mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; - } else { - return pressed == mapped ? 'full' : - mapped.indexOf(pressed) == 0 ? 'partial' : false; - } - } - function lastChar(keys) { - var match = /^.*(<[\w\-]+>)$/.exec(keys); - var selectedCharacter = match ? match[1] : keys.slice(-1); - if (selectedCharacter.length > 1){ - switch(selectedCharacter){ - case '': - selectedCharacter='\n'; - break; - case '': - selectedCharacter=' '; - break; - default: - break; - } - } - return selectedCharacter; - } - function repeatFn(cm, fn, repeat) { - return function() { - for (var i = 0; i < repeat; i++) { - fn(cm); - } - }; - } - function copyCursor(cur) { - return Pos(cur.line, cur.ch); - } - function cursorEqual(cur1, cur2) { - return cur1.ch == cur2.ch && cur1.line == cur2.line; - } - function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true; - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true; - } - return false; - } - function cursorMin(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur1 : cur2; - } - function cursorMax(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur2 : cur1; - } - function cursorIsBetween(cur1, cur2, cur3) { - // returns true if cur2 is between cur1 and cur3. - var cur1before2 = cursorIsBefore(cur1, cur2); - var cur2before3 = cursorIsBefore(cur2, cur3); - return cur1before2 && cur2before3; - } - function lineLength(cm, lineNum) { - return cm.getLine(lineNum).length; - } - function trim(s) { - if (s.trim) { - return s.trim(); - } - return s.replace(/^\s+|\s+$/g, ''); - } - function escapeRegex(s) { - return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); - } - function extendLineToColumn(cm, lineNum, column) { - var endCh = lineLength(cm, lineNum); - var spaces = new Array(column-endCh+1).join(' '); - cm.setCursor(Pos(lineNum, endCh)); - cm.replaceRange(spaces, cm.getCursor()); - } - // This functions selects a rectangular block - // of text with selectionEnd as any of its corner - // Height of block: - // Difference in selectionEnd.line and first/last selection.line - // Width of the block: - // Distance between selectionEnd.ch and any(first considered here) selection.ch - function selectBlock(cm, selectionEnd) { - var selections = [], ranges = cm.listSelections(); - var head = copyCursor(cm.clipPos(selectionEnd)); - var isClipped = !cursorEqual(selectionEnd, head); - var curHead = cm.getCursor('head'); - var primIndex = getIndex(ranges, curHead); - var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); - var max = ranges.length - 1; - var index = max - primIndex > primIndex ? max : 0; - var base = ranges[index].anchor; - - var firstLine = Math.min(base.line, head.line); - var lastLine = Math.max(base.line, head.line); - var baseCh = base.ch, headCh = head.ch; - - var dir = ranges[index].head.ch - baseCh; - var newDir = headCh - baseCh; - if (dir > 0 && newDir <= 0) { - baseCh++; - if (!isClipped) { headCh--; } - } else if (dir < 0 && newDir >= 0) { - baseCh--; - if (!wasClipped) { headCh++; } - } else if (dir < 0 && newDir == -1) { - baseCh--; - headCh++; - } - for (var line = firstLine; line <= lastLine; line++) { - var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; - selections.push(range); - } - primIndex = head.line == lastLine ? selections.length - 1 : 0; - cm.setSelections(selections); - selectionEnd.ch = headCh; - base.ch = baseCh; - return base; - } - function selectForInsert(cm, head, height) { - var sel = []; - for (var i = 0; i < height; i++) { - var lineHead = offsetCursor(head, i, 0); - sel.push({anchor: lineHead, head: lineHead}); - } - cm.setSelections(sel, 0); - } - // getIndex returns the index of the cursor in the selections. - function getIndex(ranges, cursor, end) { - for (var i = 0; i < ranges.length; i++) { - var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); - var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); - if (atAnchor || atHead) { - return i; - } - } - return -1; - } - function getSelectedAreaRange(cm, vim) { - var lastSelection = vim.lastSelection; - var getCurrentSelectedAreaRange = function() { - var selections = cm.listSelections(); - var start = selections[0]; - var end = selections[selections.length-1]; - var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - return [selectionStart, selectionEnd]; - }; - var getLastSelectedAreaRange = function() { - var selectionStart = cm.getCursor(); - var selectionEnd = cm.getCursor(); - var block = lastSelection.visualBlock; - if (block) { - var width = block.width; - var height = block.height; - selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); - var selections = []; - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - for (var i = selectionStart.line; i < selectionEnd.line; i++) { - var anchor = Pos(i, selectionStart.ch); - var head = Pos(i, selectionEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - } else { - var start = lastSelection.anchorMark.find(); - var end = lastSelection.headMark.find(); - var line = end.line - start.line; - var ch = end.ch - start.ch; - selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; - if (lastSelection.visualLine) { - selectionStart = Pos(selectionStart.line, 0); - selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); - } - cm.setSelection(selectionStart, selectionEnd); - } - return [selectionStart, selectionEnd]; - }; - if (!vim.visualMode) { - // In case of replaying the action. - return getLastSelectedAreaRange(); - } else { - return getCurrentSelectedAreaRange(); - } - } - // Updates the previous selection with the current selection's values. This - // should only be called in visual mode. - function updateLastSelection(cm, vim) { - var anchor = vim.sel.anchor; - var head = vim.sel.head; - // To accommodate the effect of lastPastedText in the last selection - if (vim.lastPastedText) { - head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); - vim.lastPastedText = null; - } - vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), - 'headMark': cm.setBookmark(head), - 'anchor': copyCursor(anchor), - 'head': copyCursor(head), - 'visualMode': vim.visualMode, - 'visualLine': vim.visualLine, - 'visualBlock': vim.visualBlock}; - } - function expandSelection(cm, start, end) { - var sel = cm.state.vim.sel; - var head = sel.head; - var anchor = sel.anchor; - var tmp; - if (cursorIsBefore(end, start)) { - tmp = end; - end = start; - start = tmp; - } - if (cursorIsBefore(head, anchor)) { - head = cursorMin(start, head); - anchor = cursorMax(anchor, end); - } else { - anchor = cursorMin(start, anchor); - head = cursorMax(head, end); - head = offsetCursor(head, 0, -1); - if (head.ch == -1 && head.line != cm.firstLine()) { - head = Pos(head.line - 1, lineLength(cm, head.line - 1)); - } - } - return [anchor, head]; - } - /** - * Updates the CodeMirror selection to match the provided vim selection. - * If no arguments are given, it uses the current vim selection state. - */ - function updateCmSelection(cm, sel, mode) { - var vim = cm.state.vim; - sel = sel || vim.sel; - var mode = mode || - vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; - var cmSel = makeCmSelection(cm, sel, mode); - cm.setSelections(cmSel.ranges, cmSel.primary); - updateFakeCursor(cm); - } - function makeCmSelection(cm, sel, mode, exclusive) { - var head = copyCursor(sel.head); - var anchor = copyCursor(sel.anchor); - if (mode == 'char') { - var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - head = offsetCursor(sel.head, 0, headOffset); - anchor = offsetCursor(sel.anchor, 0, anchorOffset); - return { - ranges: [{anchor: anchor, head: head}], - primary: 0 - }; - } else if (mode == 'line') { - if (!cursorIsBefore(sel.head, sel.anchor)) { - anchor.ch = 0; - - var lastLine = cm.lastLine(); - if (head.line > lastLine) { - head.line = lastLine; - } - head.ch = lineLength(cm, head.line); - } else { - head.ch = 0; - anchor.ch = lineLength(cm, anchor.line); - } - return { - ranges: [{anchor: anchor, head: head}], - primary: 0 - }; - } else if (mode == 'block') { - var top = Math.min(anchor.line, head.line), - left = Math.min(anchor.ch, head.ch), - bottom = Math.max(anchor.line, head.line), - right = Math.max(anchor.ch, head.ch) + 1; - var height = bottom - top + 1; - var primary = head.line == top ? 0 : height - 1; - var ranges = []; - for (var i = 0; i < height; i++) { - ranges.push({ - anchor: Pos(top + i, left), - head: Pos(top + i, right) - }); - } - return { - ranges: ranges, - primary: primary - }; - } - } - function getHead(cm) { - var cur = cm.getCursor('head'); - if (cm.getSelection().length == 1) { - // Small corner case when only 1 character is selected. The "real" - // head is the left of head and anchor. - cur = cursorMin(cur, cm.getCursor('anchor')); - } - return cur; - } - - /** - * If moveHead is set to false, the CodeMirror selection will not be - * touched. The caller assumes the responsibility of putting the cursor - * in the right place. - */ - function exitVisualMode(cm, moveHead) { - var vim = cm.state.vim; - if (moveHead !== false) { - cm.setCursor(clipCursorToContent(cm, vim.sel.head)); - } - updateLastSelection(cm, vim); - vim.visualMode = false; - vim.visualLine = false; - vim.visualBlock = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - } - - // Remove any trailing newlines from the selection. For - // example, with the caret at the start of the last word on the line, - // 'dw' should word, but not the newline, while 'w' should advance the - // caret to the first character of the next line. - function clipToLine(cm, curStart, curEnd) { - var selection = cm.getRange(curStart, curEnd); - // Only clip if the selection ends with trailing newline + whitespace - if (/\n\s*$/.test(selection)) { - var lines = selection.split('\n'); - // We know this is all whitepsace. - lines.pop(); - - // Cases: - // 1. Last word is an empty line - do not clip the trailing '\n' - // 2. Last word is not an empty line - clip the trailing '\n' - var line; - // Find the line containing the last word, and clip all whitespace up - // to it. - for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { - curEnd.line--; - curEnd.ch = 0; - } - // If the last word is not an empty line, clip an additional newline - if (line) { - curEnd.line--; - curEnd.ch = lineLength(cm, curEnd.line); - } else { - curEnd.ch = 0; - } - } - } - - // Expand the selection to line ends. - function expandSelectionToLine(_cm, curStart, curEnd) { - curStart.ch = 0; - curEnd.ch = 0; - curEnd.line++; - } - - function findFirstNonWhiteSpaceCharacter(text) { - if (!text) { - return 0; - } - var firstNonWS = text.search(/\S/); - return firstNonWS == -1 ? text.length : firstNonWS; - } - - function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = getHead(cm); - var line = cm.getLine(cur.line); - var idx = cur.ch; - - // Seek to first word or non-whitespace character, depending on if - // noSymbol is true. - var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0]; - while (!test(line.charAt(idx))) { - idx++; - if (idx >= line.length) { return null; } - } - - if (bigWord) { - test = bigWordCharTest[0]; - } else { - test = wordCharTest[0]; - if (!test(line.charAt(idx))) { - test = wordCharTest[1]; - } - } - - 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, 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, start), end: Pos(cur.line, end) }; - } - - function recordJumpPosition(cm, oldCur, newCur) { - if (!cursorEqual(oldCur, newCur)) { - vimGlobalState.jumpList.add(cm, oldCur, newCur); - } - } - - function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastChararacterSearch.increment = increment; - vimGlobalState.lastChararacterSearch.forward = args.forward; - vimGlobalState.lastChararacterSearch.selectedCharacter = args.selectedCharacter; - } - - var symbolToMode = { - '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', - '[': 'section', ']': 'section', - '*': 'comment', '/': 'comment', - 'm': 'method', 'M': 'method', - '#': 'preprocess' - }; - var findSymbolModes = { - bracket: { - isComplete: function(state) { - if (state.nextCh === state.symb) { - state.depth++; - if (state.depth >= 1)return true; - } else if (state.nextCh === state.reverseSymb) { - state.depth--; - } - return false; - } - }, - section: { - init: function(state) { - state.curMoveThrough = true; - state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; - }, - isComplete: function(state) { - return state.index === 0 && state.nextCh === state.symb; - } - }, - comment: { - isComplete: function(state) { - var found = state.lastCh === '*' && state.nextCh === '/'; - state.lastCh = state.nextCh; - return found; - } - }, - // TODO: The original Vim implementation only operates on level 1 and 2. - // The current implementation doesn't check for code block level and - // therefore it operates on any levels. - method: { - init: function(state) { - state.symb = (state.symb === 'm' ? '{' : '}'); - state.reverseSymb = state.symb === '{' ? '}' : '{'; - }, - isComplete: function(state) { - if (state.nextCh === state.symb)return true; - return false; - } - }, - preprocess: { - init: function(state) { - state.index = 0; - }, - isComplete: function(state) { - if (state.nextCh === '#') { - var token = state.lineText.match(/#(\w+)/)[1]; - if (token === 'endif') { - if (state.forward && state.depth === 0) { - return true; - } - state.depth++; - } else if (token === 'if') { - if (!state.forward && state.depth === 0) { - return true; - } - state.depth--; - } - if (token === 'else' && state.depth === 0)return true; - } - return false; - } - } - }; - function findSymbol(cm, repeat, forward, symb) { - var cur = copyCursor(cm.getCursor()); - var increment = forward ? 1 : -1; - var endLine = forward ? cm.lineCount() : -1; - var curCh = cur.ch; - var line = cur.line; - var lineText = cm.getLine(line); - var state = { - lineText: lineText, - nextCh: lineText.charAt(curCh), - lastCh: null, - index: curCh, - symb: symb, - reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], - forward: forward, - depth: 0, - curMoveThrough: false - }; - var mode = symbolToMode[symb]; - if (!mode)return cur; - var init = findSymbolModes[mode].init; - var isComplete = findSymbolModes[mode].isComplete; - if (init) { init(state); } - while (line !== endLine && repeat) { - state.index += increment; - state.nextCh = state.lineText.charAt(state.index); - if (!state.nextCh) { - line += increment; - state.lineText = cm.getLine(line) || ''; - if (increment > 0) { - state.index = 0; - } else { - var lineLen = state.lineText.length; - state.index = (lineLen > 0) ? (lineLen-1) : 0; - } - state.nextCh = state.lineText.charAt(state.index); - } - if (isComplete(state)) { - cur.line = line; - cur.ch = state.index; - repeat--; - } - } - if (state.nextCh || state.curMoveThrough) { - return Pos(line, state.index); - } - return cur; - } - - /* - * Returns the boundaries of the next word. If the cursor in the middle of - * the word, then returns the boundaries of the current word, starting at - * the cursor. If the cursor is at the start/end of a word, and we are going - * forward/backward, respectively, find the boundaries of the next word. - * - * @param {CodeMirror} cm CodeMirror object. - * @param {Cursor} cur The cursor position. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only [a-zA-Z0-9] characters count as part of the word. - * @param {boolean} emptyLineIsWord True if empty lines should be treated - * as words. - * @return {Object{from:number, to:number, line: number}} The boundaries of - * the word, or null if there are no more words. - */ - function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { - var lineNum = cur.line; - var pos = cur.ch; - var line = cm.getLine(lineNum); - var dir = forward ? 1 : -1; - var charTests = bigWord ? bigWordCharTest: wordCharTest; - - if (emptyLineIsWord && line == '') { - lineNum += dir; - line = cm.getLine(lineNum); - if (!isLine(cm, lineNum)) { - return null; - } - pos = (forward) ? 0 : line.length; - } - - while (true) { - if (emptyLineIsWord && line == '') { - return { from: 0, to: 0, line: lineNum }; - } - var stop = (dir > 0) ? line.length : -1; - var wordStart = stop, wordEnd = stop; - // Find bounds of next word. - while (pos != stop) { - var foundWord = false; - 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 && charTests[i](line.charAt(pos))) { - pos += dir; - } - wordEnd = pos; - foundWord = wordStart != wordEnd; - if (wordStart == cur.ch && lineNum == cur.line && - wordEnd == wordStart + dir) { - // We started at the end of a word. Find the next one. - continue; - } else { - return { - from: Math.min(wordStart, wordEnd + 1), - to: Math.max(wordStart, wordEnd), - line: lineNum }; - } - } - } - if (!foundWord) { - pos += dir; - } - } - // Advance to next/prev line. - lineNum += dir; - if (!isLine(cm, lineNum)) { - return null; - } - line = cm.getLine(lineNum); - pos = (dir > 0) ? 0 : line.length; - } - // Should never get here. - throw new Error('The impossible happened.'); - } - - /** - * @param {CodeMirror} cm CodeMirror object. - * @param {Pos} cur The position to start from. - * @param {int} repeat Number of words to move past. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} wordEnd True to move to end of word. False to move to - * beginning of word. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only alphabet characters count as part of the word. - * @return {Cursor} The position the cursor should move to. - */ - function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { - var curStart = copyCursor(cur); - var words = []; - if (forward && !wordEnd || !forward && wordEnd) { - repeat++; - } - // For 'e', empty lines are not considered words, go figure. - var emptyLineIsWord = !(forward && wordEnd); - for (var i = 0; i < repeat; i++) { - var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); - if (!word) { - var eodCh = lineLength(cm, cm.lastLine()); - words.push(forward - ? {line: cm.lastLine(), from: eodCh, to: eodCh} - : {line: 0, from: 0, to: 0}); - break; - } - words.push(word); - cur = Pos(word.line, forward ? (word.to - 1) : word.from); - } - var shortCircuit = words.length != repeat; - var firstWord = words[0]; - var lastWord = words.pop(); - if (forward && !wordEnd) { - // w - if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.from); - } else if (forward && wordEnd) { - return Pos(lastWord.line, lastWord.to - 1); - } else if (!forward && wordEnd) { - // ge - if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.to); - } else { - // b - return Pos(lastWord.line, lastWord.from); - } - } - - function moveToCharacter(cm, repeat, forward, character) { - var cur = cm.getCursor(); - var start = cur.ch; - var idx; - for (var i = 0; i < repeat; i ++) { - var line = cm.getLine(cur.line); - idx = charIdxInLine(start, line, character, forward, true); - if (idx == -1) { - return null; - } - start = idx; - } - return Pos(cm.getCursor().line, idx); - } - - function moveToColumn(cm, repeat) { - // repeat is always >= 1, so repeat - 1 always corresponds - // to the column we want to go to. - var line = cm.getCursor().line; - return clipCursorToContent(cm, Pos(line, repeat - 1)); - } - - function updateMark(cm, vim, markName, pos) { - if (!inArray(markName, validMarks)) { - return; - } - if (vim.marks[markName]) { - vim.marks[markName].clear(); - } - vim.marks[markName] = cm.setBookmark(pos); - } - - function charIdxInLine(start, line, character, forward, includeChar) { - // Search for char in line. - // motion_options: {forward, includeChar} - // If includeChar = true, include it too. - // If forward = true, search forward, else search backwards. - // If char is not found on this line, do nothing - var idx; - if (forward) { - idx = line.indexOf(character, start + 1); - if (idx != -1 && !includeChar) { - idx -= 1; - } - } else { - idx = line.lastIndexOf(character, start - 1); - if (idx != -1 && !includeChar) { - idx += 1; - } - } - return idx; - } - - function findParagraph(cm, head, repeat, dir, inclusive) { - var line = head.line; - var min = cm.firstLine(); - var max = cm.lastLine(); - var start, end, i = line; - 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); - } - if (dir) { - while (min <= i && i <= max && repeat > 0) { - if (isBoundary(i, dir)) { repeat--; } - i += dir; - } - return new Pos(i, 0); - } - - var vim = cm.state.vim; - if (vim.visualLine && isBoundary(line, 1, true)) { - var anchor = vim.sel.anchor; - if (isBoundary(anchor.line, -1, true)) { - if (!inclusive || anchor.line != line) { - line += 1; - } - } - } - var startState = isEmpty(line); - for (i = line; i <= max && repeat; i++) { - if (isBoundary(i, 1, true)) { - if (!inclusive || isEmpty(i) != startState) { - repeat--; - } - } - } - end = new Pos(i, 0); - // select boundary before paragraph for the last one - if (i > max && !startState) { startState = true; } - else { inclusive = false; } - for (i = line; i > min; i--) { - if (!inclusive || isEmpty(i) == startState || i == line) { - if (isBoundary(i, -1, true)) { break; } - } - } - start = new Pos(i, 0); - return { start: start, end: end }; - } - - // TODO: perhaps this finagling of start and end positions belonds - // in codmirror/replaceRange? - function selectCompanionObject(cm, head, symb, inclusive) { - var cur = head, start, end; - - var bracketRegexp = ({ - '(': /[()]/, ')': /[()]/, - '[': /[[\]]/, ']': /[[\]]/, - '{': /[{}]/, '}': /[{}]/})[symb]; - var openSym = ({ - '(': '(', ')': '(', - '[': '[', ']': '[', - '{': '{', '}': '{'})[symb]; - var curChar = cm.getLine(cur.line).charAt(cur.ch); - // Due to the behavior of scanForBracket, we need to add an offset if the - // cursor is on a matching open bracket. - var offset = curChar === openSym ? 1 : 0; - - start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); - end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); - - if (!start || !end) { - return { start: cur, end: cur }; - } - - start = start.pos; - end = end.pos; - - if ((start.line == end.line && start.ch > end.ch) - || (start.line > end.line)) { - var tmp = start; - start = end; - end = tmp; - } - - if (inclusive) { - end.ch += 1; - } else { - start.ch += 1; - } - - return { start: start, end: end }; - } - - // Takes in a symbol and a cursor and tries to simulate text objects that - // have identical opening and closing symbols - // TODO support across multiple lines - function findBeginningAndEnd(cm, head, symb, inclusive) { - var cur = copyCursor(head); - var line = cm.getLine(cur.line); - var chars = line.split(''); - var start, end, i, len; - var firstIndex = chars.indexOf(symb); - - // the decision tree is to always look backwards for the beginning first, - // but if the cursor is in front of the first instance of the symb, - // then move the cursor forward - if (cur.ch < firstIndex) { - cur.ch = firstIndex; - // Why is this line even here??? - // cm.setCursor(cur.line, firstIndex+1); - } - // otherwise if the cursor is currently on the closing symbol - else if (firstIndex < cur.ch && chars[cur.ch] == symb) { - end = cur.ch; // assign end to the current cursor - --cur.ch; // make sure to look backwards - } - - // if we're currently on the symbol, we've got a start - if (chars[cur.ch] == symb && !end) { - start = cur.ch + 1; // assign start to ahead of the cursor - } else { - // go backwards to find the start - for (i = cur.ch; i > -1 && !start; i--) { - if (chars[i] == symb) { - start = i + 1; - } - } - } - - // look forwards for the end symbol - if (start && !end) { - for (i = start, len = chars.length; i < len && !end; i++) { - if (chars[i] == symb) { - end = i; - } - } - } - - // nothing found - if (!start || !end) { - return { start: cur, end: cur }; - } - - // include the symbols - if (inclusive) { - --start; ++end; - } - - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - }; - } - - // Search functions - defineOption('pcre', true, 'boolean'); - function SearchState() {} - SearchState.prototype = { - getQuery: function() { - return vimGlobalState.query; - }, - setQuery: function(query) { - vimGlobalState.query = query; - }, - getOverlay: function() { - return this.searchOverlay; - }, - setOverlay: function(overlay) { - this.searchOverlay = overlay; - }, - isReversed: function() { - return vimGlobalState.isReversed; - }, - setReversed: function(reversed) { - vimGlobalState.isReversed = reversed; - }, - getScrollbarAnnotate: function() { - return this.annotate; - }, - setScrollbarAnnotate: function(annotate) { - this.annotate = annotate; - } - }; - function getSearchState(cm) { - var vim = cm.state.vim; - return vim.searchState_ || (vim.searchState_ = new SearchState()); - } - 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, - selectValueOnOpen: false}); - } - else { - onClose(prompt(shortText, '')); - } - } - function splitBySlash(argString) { - var slashes = findUnescapedSlashes(argString) || []; - if (!slashes.length) return []; - var tokens = []; - // in case of strings like foo/bar - if (slashes[0] !== 0) return; - for (var i = 0; i < slashes.length; i++) { - if (typeof slashes[i] == 'number') - tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); - } - return tokens; - } - - function findUnescapedSlashes(str) { - var escapeNextChar = false; - var slashes = []; - for (var i = 0; i < str.length; i++) { - var c = str.charAt(i); - if (!escapeNextChar && c == '/') { - slashes.push(i); - } - escapeNextChar = !escapeNextChar && (c == '\\'); - } - return slashes; - } - - // Translates a search string from ex (vim) syntax into javascript form. - function translateRegex(str) { - // When these match, add a '\' if unescaped or remove one if escaped. - var specials = '|(){'; - // Remove, but never add, a '\' for these. - var unescape = '}'; - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - var specialComesNext = (n && specials.indexOf(n) != -1); - if (escapeNextChar) { - if (c !== '\\' || !specialComesNext) { - out.push(c); - } - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - // Treat the unescape list as special for removing, but not adding '\'. - if (n && unescape.indexOf(n) != -1) { - specialComesNext = true; - } - // Not passing this test means removing a '\'. - if (!specialComesNext || n === '\\') { - out.push(c); - } - } else { - out.push(c); - if (specialComesNext && n !== '\\') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Translates the replace part of a search and replace from ex (vim) syntax into - // javascript form. Similar to translateRegex, but additionally fixes back references - // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. - function translateRegexReplace(str) { - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - if (escapeNextChar) { - // At any point in the loop, escapeNextChar is true if the previous - // character was a '\' and was not escaped. - out.push(c); - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - if ((isNumber(n) || n === '$')) { - out.push('$'); - } else if (n !== '/' && n !== '\\') { - out.push('\\'); - } - } else { - if (c === '$') { - out.push('$'); - } - out.push(c); - if (n === '/') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Unescape \ and / in the replace part, for PCRE mode. - function unescapeRegexReplace(str) { - var stream = new CodeMirror.StringStream(str); - var output = []; - while (!stream.eol()) { - // Search for \. - while (stream.peek() && stream.peek() != '\\') { - output.push(stream.next()); - } - if (stream.match('\\/', true)) { - // \/ => / - output.push('/'); - } else if (stream.match('\\\\', true)) { - // \\ => \ - output.push('\\'); - } else { - // Don't change anything - output.push(stream.next()); - } - } - return output.join(''); - } - - /** - * Extract the regular expression from the query and return a Regexp object. - * Returns null if the query is blank. - * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. - * If smartCase is passed in, and the query contains upper case letters, - * then ignoreCase is overridden, and the 'i' flag will not be set. - * If the query contains the /i in the flag part of the regular expression, - * then both ignoreCase and smartCase are ignored, and 'i' will be passed - * through to the Regex object. - */ - function parseQuery(query, ignoreCase, smartCase) { - // First update the last search register - var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); - lastSearchRegister.setText(query); - // Check if the query is already a regex. - if (query instanceof RegExp) { return query; } - // First try to extract regex + flags from the input. If no flags found, - // extract just the regex. IE does not accept flags directly defined in - // the regex string in the form /regex/flags - var slashes = findUnescapedSlashes(query); - var regexPart; - var forceIgnoreCase; - if (!slashes.length) { - // Query looks like 'regexp' - regexPart = query; - } else { - // Query looks like 'regexp/...' - regexPart = query.substring(0, slashes[0]); - var flagsPart = query.substring(slashes[0]); - forceIgnoreCase = (flagsPart.indexOf('i') != -1); - } - if (!regexPart) { - return null; - } - if (!getOption('pcre')) { - regexPart = translateRegex(regexPart); - } - if (smartCase) { - ignoreCase = (/^[^A-Z]*$/).test(regexPart); - } - var regexp = new RegExp(regexPart, - (ignoreCase || forceIgnoreCase) ? 'i' : undefined); - return regexp; - } - function showConfirm(cm, text) { - if (cm.openNotification) { - cm.openNotification('' + text + '', - {bottom: true, duration: 5000}); - } else { - alert(text); - } - } - function makePrompt(prefix, desc) { - var raw = ''; - if (prefix) { - raw += '' + prefix + ''; - } - raw += ' ' + - ''; - if (desc) { - raw += ''; - raw += desc; - raw += ''; - } - return raw; - } - var searchPromptDesc = '(Javascript regexp)'; - function showPrompt(cm, options) { - var shortText = (options.prefix || '') + ' ' + (options.desc || ''); - var prompt = makePrompt(options.prefix, options.desc); - dialog(cm, prompt, shortText, options.onClose, options); - } - function regexEqual(r1, r2) { - if (r1 instanceof RegExp && r2 instanceof RegExp) { - var props = ['global', 'multiline', 'ignoreCase', 'source']; - for (var i = 0; i < props.length; i++) { - var prop = props[i]; - if (r1[prop] !== r2[prop]) { - return false; - } - } - return true; - } - return false; - } - // Returns true if the query is valid. - function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { - if (!rawQuery) { - return; - } - var state = getSearchState(cm); - var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); - if (!query) { - return; - } - highlightSearchMatches(cm, query); - if (regexEqual(query, state.getQuery())) { - return query; - } - state.setQuery(query); - return query; - } - function searchOverlay(query) { - if (query.source.charAt(0) == '^') { - var matchSol = true; - } - return { - token: function(stream) { - if (matchSol && !stream.sol()) { - stream.skipToEnd(); - return; - } - var match = stream.match(query, false); - if (match) { - if (match[0].length == 0) { - // Matched empty string, skip to next. - stream.next(); - return 'searching'; - } - if (!stream.sol()) { - // Backtrack 1 to match \b - stream.backUp(1); - if (!query.exec(stream.next() + match[0])) { - stream.next(); - return null; - } - } - stream.match(query); - return 'searching'; - } - while (!stream.eol()) { - stream.next(); - if (stream.match(query, false)) break; - } - }, - query: query - }; - } - function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm); - var overlay = searchState.getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear(); - } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); - } - searchState.setOverlay(overlay); - } - } - function findNext(cm, prev, query, repeat) { - if (repeat === undefined) { repeat = 1; } - return cm.operation(function() { - var pos = cm.getCursor(); - var cursor = cm.getSearchCursor(query, pos); - for (var i = 0; i < repeat; i++) { - var found = cursor.find(prev); - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } - if (!found) { - // SearchCursor may have returned null because it hit EOF, wrap - // around and try again. - cursor = cm.getSearchCursor(query, - (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); - if (!cursor.find(prev)) { - return; - } - } - } - return cursor.from(); - }); - } - function clearSearchHighlight(cm) { - var state = getSearchState(cm); - cm.removeOverlay(getSearchState(cm).getOverlay()); - state.setOverlay(null); - if (state.getScrollbarAnnotate()) { - state.getScrollbarAnnotate().clear(); - state.setScrollbarAnnotate(null); - } - } - /** - * Check if pos is in the specified range, INCLUSIVE. - * Range can be specified with 1 or 2 arguments. - * If the first range argument is an array, treat it as an array of line - * numbers. Match pos against any of the lines. - * If the first range argument is a number, - * if there is only 1 range argument, check if pos has the same line - * number - * if there are 2 range arguments, then check if pos is in between the two - * range arguments. - */ - function isInRange(pos, start, end) { - if (typeof pos != 'number') { - // Assume it is a cursor position. Get the line number. - pos = pos.line; - } - if (start instanceof Array) { - return inArray(pos, start); - } else { - if (end) { - return (pos >= start && pos <= end); - } else { - return pos == start; - } - } - } - function getUserVisibleLines(cm) { - var renderer = cm.ace.renderer; - return { - top: renderer.getFirstFullyVisibleRow(), - bottom: renderer.getLastFullyVisibleRow() - } - } - - // Ex command handling - // Care must be taken when adding to the default Ex command map. For any - // 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' }, - { name: 'vmap', shortName: 'vm' }, - { name: 'unmap' }, - { name: 'write', shortName: 'w' }, - { name: 'undo', shortName: 'u' }, - { name: 'redo', shortName: 'red' }, - { 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' }, - { name: 'delmarks', shortName: 'delm' }, - { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, - { name: 'global', shortName: 'g' } - ]; - var ExCommandDispatcher = function() { - this.buildCommandMap_(); - }; - 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(); - if (vim.visualMode) { - exitVisualMode(cm); - } - var inputStream = new CodeMirror.StringStream(input); - // update ": with the latest command whether valid or invalid - commandHistoryRegister.setText(input); - var params = opt_params || {}; - params.input = input; - try { - this.parseInput_(cm, inputStream, params); - } catch(e) { - showConfirm(cm, e); - throw e; - } - var command; - var commandName; - if (!params.commandName) { - // If only a line range is defined, move to the line. - if (params.line !== undefined) { - commandName = 'move'; - } - } else { - command = this.matchCommand_(params.commandName); - if (command) { - commandName = command.name; - if (command.excludeFromCommandHistory) { - commandHistoryRegister.setText(previousCommand); - } - this.parseCommandArgs_(inputStream, params, command); - if (command.type == 'exToKey') { - // Handle Ex to Key mapping. - for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); - } - return; - } else if (command.type == 'exToEx') { - // Handle Ex to Ex mapping. - this.processCommand(cm, command.toInput); - return; - } - } - } - if (!commandName) { - showConfirm(cm, 'Not an editor command ":' + input + '"'); - return; - } - try { - exCommands[commandName](cm, params); - // Possibly asynchronous commands (e.g. substitute, which might have a - // user confirmation), are responsible for calling the callback when - // done. All others have it taken care of for them here. - if ((!command || !command.possiblyAsync) && params.callback) { - params.callback(); - } - } catch(e) { - showConfirm(cm, e); - throw e; - } - }, - parseInput_: function(cm, inputStream, result) { - inputStream.eatWhile(':'); - // Parse range. - if (inputStream.eat('%')) { - result.line = cm.firstLine(); - result.lineEnd = cm.lastLine(); - } else { - result.line = this.parseLineSpec_(cm, inputStream); - if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream); - } - } - - // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/); - if (commandMatch) { - result.commandName = commandMatch[1]; - } else { - result.commandName = inputStream.match(/.*/)[0]; - } - - return result; - }, - parseLineSpec_: function(cm, inputStream) { - var numberMatch = inputStream.match(/^(\d+)/); - if (numberMatch) { - return parseInt(numberMatch[1], 10) - 1; - } - switch (inputStream.next()) { - case '.': - return cm.getCursor().line; - case '$': - return cm.lastLine(); - case '\'': - var mark = cm.state.vim.marks[inputStream.next()]; - if (mark && mark.find()) { - return mark.find().line; - } - throw new Error('Mark not set'); - default: - inputStream.backUp(1); - return undefined; - } - }, - parseCommandArgs_: function(inputStream, params, command) { - if (inputStream.eol()) { - return; - } - params.argString = inputStream.match(/.*/)[0]; - // Parse command-line arguments - var delim = command.argDelimiter || /\s+/; - var args = trim(params.argString).split(delim); - if (args.length && args[0]) { - params.args = args; - } - }, - matchCommand_: function(commandName) { - // Return the command in the command map that matches the shortest - // prefix of the passed in command name. The match is guaranteed to be - // unambiguous if the defaultExCommandMap's shortNames are set up - // correctly. (see @code{defaultExCommandMap}). - for (var i = commandName.length; i > 0; i--) { - var prefix = commandName.substring(0, i); - if (this.commandMap_[prefix]) { - var command = this.commandMap_[prefix]; - if (command.name.indexOf(commandName) === 0) { - return command; - } - } - } - return null; - }, - buildCommandMap_: function() { - this.commandMap_ = {}; - for (var i = 0; i < defaultExCommandMap.length; i++) { - var command = defaultExCommandMap[i]; - var key = command.shortName || command.name; - this.commandMap_[key] = command; - } - }, - map: function(lhs, rhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (rhs != ':' && rhs.charAt(0) == ':') { - // Ex to Ex mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToEx', - toInput: rhs.substring(1), - user: true - }; - } else { - // Ex to key mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToKey', - toKeys: rhs, - user: true - }; - } - } else { - if (rhs != ':' && rhs.charAt(0) == ':') { - // Key to Ex mapping. - var mapping = { - keys: lhs, - type: 'keyToEx', - exArgs: { input: rhs.substring(1) }, - user: true}; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } else { - // Key to key mapping - var mapping = { - keys: lhs, - type: 'keyToKey', - toKeys: rhs, - user: true - }; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } - } - }, - unmap: function(lhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - // Ex to Ex or Ex to key mapping - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { - delete this.commandMap_[commandName]; - return; - } - } else { - // Key to Ex or key to key mapping - var keys = lhs; - for (var i = 0; i < defaultKeymap.length; i++) { - if (keys == defaultKeymap[i].keys - && defaultKeymap[i].context === ctx - && defaultKeymap[i].user) { - defaultKeymap.splice(i, 1); - return; - } - } - } - throw Error('No such mapping.'); - } - }; - - 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) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); - }, - imap: function(cm, params) { this.map(cm, params, 'insert'); }, - nmap: function(cm, params) { this.map(cm, params, 'normal'); }, - vmap: function(cm, params) { this.map(cm, params, 'visual'); }, - unmap: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 1) { - if (cm) { - showConfirm(cm, 'No such mapping: ' + params.input); - } - return; - } - exCommandDispatcher.unmap(mapArgs[0], ctx); - }, - move: function(cm, params) { - commandDispatcher.processCommand(cm, cm.state.vim, { - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, - linewise: true }, - repeatOverride: params.line+1}); - }, - 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); - } - return; - } - var expr = setArgs[0].split('='); - var optionName = expr[0]; - var value = expr[1]; - var forceGet = false; - - if (optionName.charAt(optionName.length - 1) == '?') { - // If post-fixed with ?, then the set is actually a get. - if (value) { throw Error('Trailing characters: ' + params.argString); } - optionName = optionName.substring(0, optionName.length - 1); - forceGet = true; - } - if (value === undefined && optionName.substring(0, 2) == 'no') { - // To set boolean options to false, the option name is prefixed with - // 'no'. - 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 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, setCfg); - } - }, - 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----------

    '; - if (!regArgs) { - for (var registerName in registers) { - var text = registers[registerName].toString(); - if (text.length) { - regInfo += '"' + registerName + ' ' + text + '
    '; - } - } - } else { - var registerName; - regArgs = regArgs.join(''); - for (var i = 0; i < regArgs.length; i++) { - registerName = regArgs.charAt(i); - if (!vimGlobalState.registerController.isValidRegister(registerName)) { - continue; - } - var register = registers[registerName] || new Register(); - regInfo += '"' + registerName + ' ' + register.toString() + '
    '; - } - } - showConfirm(cm, regInfo); - }, - sort: function(cm, params) { - var reverse, ignoreCase, unique, number; - function parseArgs() { - if (params.argString) { - var args = new CodeMirror.StringStream(params.argString); - if (args.eat('!')) { reverse = true; } - if (args.eol()) { return; } - if (!args.eatSpace()) { return 'Invalid arguments'; } - var opts = args.match(/[a-z]+/); - if (opts) { - opts = opts[0]; - ignoreCase = opts.indexOf('i') != -1; - unique = opts.indexOf('u') != -1; - var decimal = opts.indexOf('d') != -1 && 1; - var hex = opts.indexOf('x') != -1 && 1; - var octal = opts.indexOf('o') != -1 && 1; - if (decimal + hex + octal > 1) { return 'Invalid arguments'; } - number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; - } - if (args.eatSpace() && args.match(/\/.*\//)) { 'patterns not supported'; } - } - } - var err = parseArgs(); - if (err) { - showConfirm(cm, err + ': ' + params.argString); - return; - } - var lineStart = params.line || cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - if (lineStart == lineEnd) { return; } - var curStart = Pos(lineStart, 0); - var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); - var text = cm.getRange(curStart, curEnd).split('\n'); - var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : - (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : - (number == 'octal') ? /([0-7]+)/ : null; - var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; - var numPart = [], textPart = []; - if (number) { - for (var i = 0; i < text.length; i++) { - if (numberRegex.exec(text[i])) { - numPart.push(text[i]); - } else { - textPart.push(text[i]); - } - } - } else { - textPart = text; - } - function compareFn(a, b) { - if (reverse) { var tmp; tmp = a; a = b; b = tmp; } - if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } - var anum = number && numberRegex.exec(a); - var bnum = number && numberRegex.exec(b); - if (!anum) { return a < b ? -1 : 1; } - anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); - bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); - return anum - bnum; - } - numPart.sort(compareFn); - textPart.sort(compareFn); - text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); - if (unique) { // Remove duplicate lines - var textOld = text; - var lastLine; - text = []; - for (var i = 0; i < textOld.length; i++) { - if (textOld[i] != lastLine) { - text.push(textOld[i]); - } - lastLine = textOld[i]; - } - } - cm.replaceRange(text.join('\n'), curStart, curEnd); - }, - global: function(cm, params) { - // a global command is of the form - // :[range]g/pattern/[cmd] - // argString holds the string /pattern/[cmd] - var argString = params.argString; - if (!argString) { - showConfirm(cm, 'Regular Expression missing from global'); - return; - } - // range is specified here - var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - // get the tokens from argString - var tokens = splitBySlash(argString); - var regexPart = argString, cmd; - if (tokens.length) { - regexPart = tokens[0]; - cmd = tokens.slice(1, tokens.length).join('/'); - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise - // use the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - // now that we have the regexPart, search for regex matches in the - // specified range of lines - var query = getSearchState(cm).getQuery(); - var matchedLines = [], content = ''; - for (var i = lineStart; i <= lineEnd; i++) { - var matched = query.test(cm.getLine(i)); - if (matched) { - matchedLines.push(i+1); - content+= cm.getLine(i) + '
    '; - } - } - // if there is no [cmd], just display the list of matched lines - if (!cmd) { - showConfirm(cm, content); - return; - } - var index = 0; - var nextCommand = function() { - if (index < matchedLines.length) { - var command = matchedLines[index] + cmd; - exCommandDispatcher.processCommand(cm, command, { - callback: nextCommand - }); - } - index++; - }; - nextCommand(); - }, - substitute: function(cm, params) { - if (!cm.getSearchCursor) { - throw new Error('Search feature not available. Requires searchcursor.js or ' + - 'any other getSearchCursor implementation.'); - } - var argString = params.argString; - var tokens = argString ? splitBySlash(argString) : []; - var regexPart, replacePart = '', trailing, flagsPart, count; - var confirm = false; // Whether to confirm each replace. - var global = false; // True to replace all instances on a line, false to replace only 1. - if (tokens.length) { - regexPart = tokens[0]; - replacePart = tokens[1]; - if (replacePart !== undefined) { - if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart); - } else { - replacePart = translateRegexReplace(replacePart); - } - vimGlobalState.lastSubstituteReplacePart = replacePart; - } - trailing = tokens[2] ? tokens[2].split(' ') : []; - } else { - // either the argString is empty or its of the form ' hello/world' - // actually splitBySlash returns a list of tokens - // only if the string starts with a '/' - if (argString && argString.length) { - showConfirm(cm, 'Substitutions should be of the form ' + - ':s/pattern/replace/'); - return; - } - } - // After the 3rd slash, we can have flags followed by a space followed - // by count. - if (trailing) { - flagsPart = trailing[0]; - count = parseInt(trailing[1]); - if (flagsPart) { - if (flagsPart.indexOf('c') != -1) { - confirm = true; - flagsPart.replace('c', ''); - } - if (flagsPart.indexOf('g') != -1) { - global = true; - flagsPart.replace('g', ''); - } - regexPart = regexPart + '/' + flagsPart; - } - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise use - // the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; - if (replacePart === undefined) { - showConfirm(cm, 'No previous substitute regular expression'); - return; - } - var state = getSearchState(cm); - var query = state.getQuery(); - var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; - var lineEnd = params.lineEnd || lineStart; - if (count) { - lineStart = lineEnd; - lineEnd = lineStart + count - 1; - } - var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); - var cursor = cm.getSearchCursor(query, startPos); - doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); - }, - redo: CodeMirror.commands.redo, - undo: CodeMirror.commands.undo, - write: function(cm) { - if (CodeMirror.commands.save) { - // If a save command is defined, call it. - CodeMirror.commands.save(cm); - } else { - // Saves to text area if no save command is defined. - cm.save(); - } - }, - nohlsearch: function(cm) { - clearSearchHighlight(cm); - }, - delmarks: function(cm, params) { - if (!params.argString || !trim(params.argString)) { - showConfirm(cm, 'Argument required'); - return; - } - - var state = cm.state.vim; - var stream = new CodeMirror.StringStream(trim(params.argString)); - while (!stream.eol()) { - stream.eatSpace(); - - // Record the streams position at the beginning of the loop for use - // in error messages. - var count = stream.pos; - - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var sym = stream.next(); - // Check if this symbol is part of a range - if (stream.match('-', true)) { - // This symbol is part of a range. - - // The range must terminate at an alphabetic character. - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var startMark = sym; - var finishMark = stream.next(); - // The range must terminate at an alphabetic character which - // shares the same case as the start of the range. - if (isLowerCase(startMark) && isLowerCase(finishMark) || - isUpperCase(startMark) && isUpperCase(finishMark)) { - var start = startMark.charCodeAt(0); - var finish = finishMark.charCodeAt(0); - if (start >= finish) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - // Because marks are always ASCII values, and we have - // determined that they are the same case, we can use - // their char codes to iterate through the defined range. - for (var j = 0; j <= finish - start; j++) { - var mark = String.fromCharCode(start + j); - delete state.marks[mark]; - } - } else { - showConfirm(cm, 'Invalid argument: ' + startMark + '-'); - return; - } - } else { - // This symbol is a valid mark, and is not part of a range. - delete state.marks[sym]; - } - } - } - }; - - var exCommandDispatcher = new ExCommandDispatcher(); - - /** - * @param {CodeMirror} cm CodeMirror instance we are in. - * @param {boolean} confirm Whether to confirm each replace. - * @param {Cursor} lineStart Line to start replacing from. - * @param {Cursor} lineEnd Line to stop replacing at. - * @param {RegExp} query Query for performing matches with. - * @param {string} replaceWith Text to replace matches with. May contain $1, - * $2, etc for replacing captured groups using Javascript replace. - * @param {function()} callback A callback for when the replace is done. - */ - function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, - replaceWith, callback) { - // Set up all the functions. - cm.state.vim.exMode = true; - var done = false; - var lastPos = searchCursor.from(); - function replaceAll() { - cm.operation(function() { - while (!done) { - replace(); - next(); - } - stop(); - }); - } - function replace() { - var text = cm.getRange(searchCursor.from(), searchCursor.to()); - var newText = text.replace(query, replaceWith); - searchCursor.replace(newText); - } - function next() { - var found; - // The below only loops to skip over multiple occurrences on the same - // line when 'global' is not true. - while(found = searchCursor.findNext() && - isInRange(searchCursor.from(), lineStart, lineEnd)) { - if (!global && lastPos && searchCursor.from().line == lastPos.line) { - continue; - } - cm.scrollIntoView(searchCursor.from(), 30); - cm.setSelection(searchCursor.from(), searchCursor.to()); - lastPos = searchCursor.from(); - done = false; - return; - } - done = true; - } - function stop(close) { - if (close) { close(); } - cm.focus(); - if (lastPos) { - cm.setCursor(lastPos); - var vim = cm.state.vim; - vim.exMode = false; - vim.lastHPos = vim.lastHSPos = lastPos.ch; - } - if (callback) { callback(); } - } - function onPromptKeyDown(e, _value, close) { - // Swallow all keys. - CodeMirror.e_stop(e); - var keyName = CodeMirror.keyName(e); - switch (keyName) { - case 'Y': - replace(); next(); break; - case 'N': - next(); break; - case 'A': - // replaceAll contains a call to close of its own. We don't want it - // to fire too early or multiple times. - var savedCallback = callback; - callback = undefined; - cm.operation(replaceAll); - callback = savedCallback; - break; - case 'L': - replace(); - // fall through and exit. - case 'Q': - case 'Esc': - case 'Ctrl-C': - case 'Ctrl-[': - stop(close); - break; - } - if (done) { stop(close); } - return true; - } - - // Actually do replace. - next(); - if (done) { - showConfirm(cm, 'No matches for ' + query.source); - return; - } - if (!confirm) { - replaceAll(); - if (callback) { callback(); }; - return; - } - showPrompt(cm, { - prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', - onKeyDown: onPromptKeyDown - }); - } - - CodeMirror.keyMap.vim = { - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - function exitInsertMode(cm) { - var vim = cm.state.vim; - var macroModeState = vimGlobalState.macroModeState; - var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); - var isPlaying = macroModeState.isPlaying; - var lastChange = macroModeState.lastInsertModeChanges; - // In case of visual block, the insertModeChanges are not saved as a - // single word, so we convert them to a single word - // so as to update the ". register as expected in real vim. - var text = []; - if (!isPlaying) { - var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; - var changes = lastChange.changes; - var text = []; - var i = 0; - // In case of multiple selections in blockwise visual, - // the inserted text, for example: 'foo', is stored as - // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). - // We push the contents of the changes array as per the following: - // 1. In case of InsertModeKey, just increment by 1. - // 2. In case of a character, jump by selLength (2 in the example). - while (i < changes.length) { - // This loop will convert 'ffoooo' to 'foo'. - text.push(changes[i]); - if (changes[i] instanceof InsertModeKey) { - i++; - } else { - i+= selLength; - } - } - lastChange.changes = text; - cm.off('change', onChange); - CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (!isPlaying && vim.insertModeRepeat > 1) { - // Perform insert mode repeat for commands like 3,a and 3,o. - repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, - true /** repeatForInsert */); - vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; - } - delete vim.insertModeRepeat; - vim.insertMode = false; - cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.toggleOverwrite(false); // exit replace mode if we were in it. - // update the ". register before exiting insert mode - insertModeChangeRegister.setText(lastChange.changes.join('')); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (macroModeState.isRecording) { - logInsertModeChange(macroModeState); - } - } - - 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'); - - CodeMirror.keyMap['vim-insert'] = { - // TODO: override navigation keys so that Esc will cancel automatic - // indentation from o, O, i_ - 'Ctrl-N': 'autocomplete', - 'Ctrl-P': 'autocomplete', - 'Enter': function(cm) { - var fn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - fn(cm); - }, - fallthrough: ['default'], - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - CodeMirror.keyMap['vim-replace'] = { - 'Backspace': 'goCharLeft', - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - function executeMacroRegister(cm, vim, macroModeState, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName); - var keyBuffer = register.keyBuffer; - var imc = 0; - macroModeState.isPlaying = true; - macroModeState.replaySearchQueries = register.searchQueries.slice(0); - for (var i = 0; i < keyBuffer.length; i++) { - var text = keyBuffer[i]; - var match, key; - while (text) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(text); - key = match[0]; - text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'macro'); - if (vim.insertMode) { - var changes = register.insertModeChanges[imc++].changes; - vimGlobalState.macroModeState.lastInsertModeChanges.changes = - changes; - repeatInsertModeChanges(cm, changes, 1); - exitInsertMode(cm); - } - } - }; - macroModeState.isPlaying = false; - } - - function logKey(macroModeState, key) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushText(key); - } - } - - function logInsertModeChange(macroModeState) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); - } - } - - function logSearchQuery(macroModeState, query) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushSearchQuery(query); - } - } - - /** - * Listens for changes made in insert mode. - * Should only be active in insert mode. - */ - function onChange(_cm, changeObj) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - if (!macroModeState.isPlaying) { - while(changeObj) { - lastChange.expectCursorActivityForChange = true; - if (changeObj.origin == '+input' || changeObj.origin == 'paste' - || changeObj.origin === undefined /* only in testing */) { - var text = changeObj.text.join('\n'); - lastChange.changes.push(text); - } - // Change objects may be chained with next. - changeObj = changeObj.next; - } - } - } - - /** - * Listens for any kind of cursor activity on CodeMirror. - */ - function onCursorActivity(cm) { - var vim = cm.state.vim; - if (vim.insertMode) { - // Tracking cursor activity in insert mode (for macro support). - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - var lastChange = macroModeState.lastInsertModeChanges; - if (lastChange.expectCursorActivityForChange) { - lastChange.expectCursorActivityForChange = false; - } else { - // Cursor moved outside the context of an edit. Reset the change. - lastChange.changes = []; - } - } else if (!cm.curOp.isVimOp) { - handleExternalSelection(cm, vim); - } - if (vim.visualMode) { - updateFakeCursor(cm); - } - } - function updateFakeCursor(cm) { - var vim = cm.state.vim; - var from = clipCursorToContent(cm, copyCursor(vim.sel.head)); - var to = offsetCursor(from, 0, 1); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); - } - function handleExternalSelection(cm, vim) { - var anchor = cm.getCursor('anchor'); - var head = cm.getCursor('head'); - // Enter or exit visual mode to match mouse selection. - if (vim.visualMode && !cm.somethingSelected()) { - exitVisualMode(cm, false); - } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); - } - if (vim.visualMode) { - // Bind CodeMirror selection model to vim selection model. - // Mouse selections are considered visual characterwise. - var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; - var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; - head = offsetCursor(head, 0, headOffset); - anchor = offsetCursor(anchor, 0, anchorOffset); - vim.sel = { - anchor: anchor, - head: head - }; - updateMark(cm, vim, '<', cursorMin(head, anchor)); - updateMark(cm, vim, '>', cursorMax(head, anchor)); - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch; - } - } - - /** Wrapper for special keys pressed in insert mode */ - function InsertModeKey(keyName) { - this.keyName = keyName; - } - - /** - * Handles raw key down events from the text area. - * - Should only be active in insert mode. - * - For recording deletes in insert mode. - */ - function onKeyEventTargetKeyDown(e) { - 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; - } - if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); - } - } - - /** - * Repeats the last edit, which includes exactly 1 command and at most 1 - * insert. Operator and motion commands are read from lastEditInputState, - * while action commands are read from lastEditActionCommand. - * - * If repeatForInsert is true, then the function was called by - * exitInsertMode to repeat the insert mode changes the user just made. The - * corresponding enterInsertMode call was made with a count. - */ - function repeatLastEdit(cm, vim, repeat, repeatForInsert) { - var macroModeState = vimGlobalState.macroModeState; - macroModeState.isPlaying = true; - var isAction = !!vim.lastEditActionCommand; - var cachedInputState = vim.inputState; - function repeatCommand() { - if (isAction) { - commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); - } else { - commandDispatcher.evalInput(cm, vim); - } - } - function repeatInsert(repeat) { - if (macroModeState.lastInsertModeChanges.changes.length > 0) { - // For some reason, repeat cw in desktop VIM does not repeat - // insert mode changes. Will conform to that behavior. - repeat = !vim.lastEditActionCommand ? 1 : repeat; - var changeObject = macroModeState.lastInsertModeChanges; - repeatInsertModeChanges(cm, changeObject.changes, repeat); - } - } - vim.inputState = vim.lastEditInputState; - if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { - // o and O repeat have to be interlaced with insert repeats so that the - // insertions appear on separate lines instead of the last line. - for (var i = 0; i < repeat; i++) { - repeatCommand(); - repeatInsert(1); - } - } else { - if (!repeatForInsert) { - // Hack to get the cursor to end up at the right place. If I is - // repeated in insert mode repeat, cursor will be 1 insert - // change set left of where it should be. - repeatCommand(); - } - repeatInsert(repeat); - } - vim.inputState = cachedInputState; - if (vim.insertMode && !repeatForInsert) { - // Don't exit insert mode twice. If repeatForInsert is set, then we - // were called by an exitInsertMode call lower on the stack. - exitInsertMode(cm); - } - macroModeState.isPlaying = false; - }; - - function repeatInsertModeChanges(cm, changes, repeat) { - function keyHandler(binding) { - if (typeof binding == 'string') { - CodeMirror.commands[binding](cm); - } else { - binding(cm); - } - return true; - } - var head = cm.getCursor('head'); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { - // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var lastSel = vim.lastSelection; - var offset = getOffset(lastSel.anchor, lastSel.head); - selectForInsert(cm, head, offset.line + 1); - repeat = cm.listSelections().length; - cm.setCursor(head); - } - for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, i, 0)); - } - for (var j = 0; j < changes.length; j++) { - var change = changes[j]; - if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); - } else { - var cur = cm.getCursor(); - cm.replaceRange(change, cur, cur); - } - } - } - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, 0, 1)); - } - } - - resetVimGlobalState(); - //}; - // Initialize Vim and make it available as an API. - CodeMirror.Vim = Vim(); - - Vim = CodeMirror.Vim; - - var specialKey = {'return':'CR',backspace:'BS','delete':'Del',esc:'Esc', - left:'Left',right:'Right',up:'Up',down:'Down',space: 'Space', - home:'Home',end:'End',pageup:'PageUp',pagedown:'PageDown', enter: 'CR' - }; - function lookupKey(hashId, key, e) { - if (key.length > 1 && key[0] == "n") { - key = key.replace("numpad", ""); - } - key = specialKey[key] || key; - var name = ''; - if (e.ctrlKey) { name += 'C-'; } - if (e.altKey) { name += 'A-'; } - if (e.shiftKey) { name += 'S-'; } - - name += key; - if (name.length > 1) { name = '<' + name + '>'; } - return name; - } - var handleKey = Vim.handleKey.bind(Vim); - Vim.handleKey = function(cm, key, origin) { - return cm.operation(function() { - return handleKey(cm, key, origin); - }, true); - } - function cloneVimState(state) { - var n = new state.constructor(); - Object.keys(state).forEach(function(key) { - var o = state[key]; - if (Array.isArray(o)) - o = o.slice(); - else if (o && typeof o == "object" && o.constructor != Object) - o = cloneVimState(o); - n[key] = o; - }); - if (state.sel) { - n.sel = { - head: state.sel.head && copyCursor(state.sel.head), - anchor: state.sel.anchor && copyCursor(state.sel.anchor) - }; - } - return n; - } - function multiSelectHandleKey(cm, key, origin) { - var isHandled = false; - var vim = Vim.maybeInitVimState_(cm); - var visualBlock = vim.visualBlock || vim.wasInVisualBlock; - if (vim.wasInVisualBlock && !cm.ace.inMultiSelectMode) { - vim.wasInVisualBlock = false; - } else if (cm.ace.inMultiSelectMode && vim.visualBlock) { - vim.wasInVisualBlock = true; - } - - if (key == '' && !vim.insertMode && !vim.visualMode && cm.ace.inMultiSelectMode) { - cm.ace.exitMultiSelectMode(); - } else if (visualBlock || !cm.ace.inMultiSelectMode || cm.ace.inVirtualSelectionMode) { - isHandled = Vim.handleKey(cm, key, origin); - } else { - var old = cloneVimState(vim); - cm.operation(function() { - cm.ace.forEachSelection(function() { - var sel = cm.ace.selection; - cm.state.vim.lastHPos = sel.$desiredColumn == null ? sel.lead.column : sel.$desiredColumn; - var head = cm.getCursor("head"); - var anchor = cm.getCursor("anchor"); - var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; - var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; - head = offsetCursor(head, 0, headOffset); - anchor = offsetCursor(anchor, 0, anchorOffset); - cm.state.vim.sel.head = head; - cm.state.vim.sel.anchor = anchor; - - isHandled = handleKey(cm, key, origin); - sel.$desiredColumn = cm.state.vim.lastHPos == -1 ? null : cm.state.vim.lastHPos; - if (cm.virtualSelectionMode()) { - cm.state.vim = cloneVimState(old); - } - }); - if (cm.curOp.cursorActivity && !isHandled) - cm.curOp.cursorActivity = false; - }, true); - } - return isHandled; - } - exports.CodeMirror = CodeMirror; - var getVim = Vim.maybeInitVimState_; - exports.handler = { - $id: "ace/keyboard/vim", - drawCursor: function(style, pixelPos, config, sel, session) { - var vim = this.state.vim || {}; - var w = config.characterWidth; - var h = config.lineHeight; - var top = pixelPos.top; - var left = pixelPos.left; - if (!vim.insertMode) { - var isbackwards = !sel.cursor - ? session.selection.isBackwards() || session.selection.isEmpty() - : Range.comparePoints(sel.cursor, sel.start) <= 0; - if (!isbackwards && left > w) - left -= w; - } - if (!vim.insertMode && vim.status) { - h = h / 2; - top += h; - } - style.left = left + "px"; - style.top = top + "px"; - style.width = w + "px"; - style.height = h + "px"; - }, - handleKeyboard: function(data, hashId, key, keyCode, e) { - var editor = data.editor; - var cm = editor.state.cm; - var vim = getVim(cm); - if (keyCode == -1) return; - - if (key == "c" && hashId == 1) { // key == "ctrl-c" - if (!useragent.isMac && editor.getCopyText()) { - editor.once("copy", function() { - editor.selection.clearSelection(); - }); - return {command: "null", passEvent: true}; - } - } else if (!vim.insertMode) { - if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { - hashId = -1; - key = data.inputChar; - } - } - - if (hashId == -1 || hashId & 1 || hashId === 0 && key.length > 1) { - var insertMode = vim.insertMode; - var name = lookupKey(hashId, key, e || {}); - if (vim.status == null) - vim.status = ""; - var isHandled = multiSelectHandleKey(cm, name, 'user'); - vim = getVim(cm); // may be changed by multiSelectHandleKey - if (isHandled && vim.status != null) - vim.status += name; - else if (vim.status == null) - vim.status = ""; - cm._signal("changeStatus"); - if (!isHandled && (hashId != -1 || insertMode)) - return; - return {command: "null", passEvent: !isHandled}; - } - }, - attach: function(editor) { - if (!editor.state) editor.state = {}; - var cm = new CodeMirror(editor); - editor.state.cm = cm; - editor.$vimModeHandler = this; - CodeMirror.keyMap.vim.attach(cm); - getVim(cm).status = null; - cm.on('vim-command-done', function() { - if (cm.virtualSelectionMode()) return; - getVim(cm).status = null; - cm.ace._signal("changeStatus"); - cm.ace.session.markUndoGroup(); - }); - cm.on("changeStatus", function() { - cm.ace.renderer.updateCursor(); - cm.ace._signal("changeStatus"); - }); - cm.on("vim-mode-change", function() { - if (cm.virtualSelectionMode()) return; - cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); - cm._signal("changeStatus"); - }); - cm.ace.renderer.setStyle("normal-mode", !getVim(cm).insertMode); - editor.renderer.$cursorLayer.drawCursor = this.drawCursor.bind(cm); - // renderVirtualNumbers.attach(editor); - this.updateMacCompositionHandlers(editor, true); - }, - detach: function(editor) { - var cm = editor.state.cm; - CodeMirror.keyMap.vim.detach(cm); - cm.destroy(); - editor.state.cm = null; - editor.$vimModeHandler = null; - editor.renderer.$cursorLayer.drawCursor = null; - editor.renderer.setStyle("normal-mode", false); - // renderVirtualNumbers.detach(editor); - this.updateMacCompositionHandlers(editor, false); - }, - getStatusText: function(editor) { - var cm = editor.state.cm; - var vim = getVim(cm); - if (vim.insertMode) - return "INSERT"; - var status = ""; - if (vim.visualMode) { - status += "VISUAL"; - if (vim.visualLine) - status += " LINE"; - if (vim.visualBlock) - status += " BLOCK"; - } - if (vim.status) - status += (status ? " " : "") + vim.status; - return status; - }, +exports.handler = { + $id: "ace/keyboard/vim", // workaround for j not repeating with `defaults write -g ApplePressAndHoldEnabled -bool true` handleMacRepeat: function(data, hashId, key) { - if (hashId == -1) { - // record key - data.inputChar = key; - data.lastEvent = "input"; - } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { - // check for repeated keypress - if (data.lastEvent == "input") { - data.lastEvent = "input1"; - } else if (data.lastEvent == "input1") { - // simulate textinput - return true; + if (hashId == -1) { + // record key + data.inputChar = key; + data.lastEvent = "input"; + } else if (data.inputChar && data.$lastHash == hashId && data.$lastKey == key) { + // check for repeated keypress + if (data.lastEvent == "input") { + data.lastEvent = "input1"; + } else if (data.lastEvent == "input1") { + // simulate textinput + return true; + } + } else { + // reset + data.$lastHash = hashId; + data.$lastKey = key; + data.lastEvent = "keypress"; } - } else { - // reset - data.$lastHash = hashId; - data.$lastKey = key; - data.lastEvent = "keypress"; - } }, // on mac, with some keyboard layouts (e.g swedish) ^ starts composition, we don't need it in normal mode updateMacCompositionHandlers: function(editor, enable) { - var onCompositionUpdateOverride = function(text) { - var cm = editor.state.cm; - var vim = getVim(cm); - if (!vim.insertMode) { - var el = this.textInput.getElement(); - el.blur(); - el.focus(); - el.value = text; + var onCompositionUpdateOverride = function(text) { + if (util.currentMode !== "insert") { + var el = this.textInput.getElement(); + el.blur(); + el.focus(); + el.value = text; + } else { + this.onCompositionUpdateOrig(text); + } + }; + var onCompositionStartOverride = function(text) { + if (util.currentMode === "insert") { + this.onCompositionStartOrig(text); + } + } + if (enable) { + if (!editor.onCompositionUpdateOrig) { + editor.onCompositionUpdateOrig = editor.onCompositionUpdate; + editor.onCompositionUpdate = onCompositionUpdateOverride; + editor.onCompositionStartOrig = editor.onCompositionStart; + editor.onCompositionStart = onCompositionStartOverride; + } } else { - this.onCompositionUpdateOrig(text); + if (editor.onCompositionUpdateOrig) { + editor.onCompositionUpdate = editor.onCompositionUpdateOrig; + editor.onCompositionUpdateOrig = null; + editor.onCompositionStart = editor.onCompositionStartOrig; + editor.onCompositionStartOrig = null; + } } - }; - var onCompositionStartOverride = function(text) { - var cm = editor.state.cm; - var vim = getVim(cm); - if (!vim.insertMode) { - this.onCompositionStartOrig(text); - } - }; - if (enable) { - if (!editor.onCompositionUpdateOrig) { - editor.onCompositionUpdateOrig = editor.onCompositionUpdate; - editor.onCompositionUpdate = onCompositionUpdateOverride; - editor.onCompositionStartOrig = editor.onCompositionStart; - editor.onCompositionStart = onCompositionStartOverride; - } - } else { - if (editor.onCompositionUpdateOrig) { - editor.onCompositionUpdate = editor.onCompositionUpdateOrig; - editor.onCompositionUpdateOrig = null; - editor.onCompositionStart = editor.onCompositionStartOrig; - editor.onCompositionStartOrig = null; - } - } - } - }; - var renderVirtualNumbers = { - getText: function(session, row) { - 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); - }, - attach: function(editor) { - editor.renderer.$gutterLayer.$renderer = this; - editor.on("changeSelection", this.update); - }, - detach: function(editor) { - editor.renderer.$gutterLayer.$renderer = null; - editor.off("changeSelection", this.update); - } - }; - Vim.defineOption({ - name: "wrap", - set: function(value, cm) { - if (cm) {cm.ace.setOption("wrap", value)} - }, - 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 } }, - { keys: 'zo', type: 'action', action: 'fold', actionArgs: { open: true, } }, - { keys: 'zO', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - { keys: 'za', type: 'action', action: 'fold', actionArgs: { toggle: true } }, - { keys: 'zA', type: 'action', action: 'fold', actionArgs: { toggle: true, all: true } }, - { keys: 'zf', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - { keys: 'zd', type: 'action', action: 'fold', actionArgs: { open: true, all: true } }, - - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAbove" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelow" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorAboveSkipCurrent" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "addCursorBelowSkipCurrent" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreBefore" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectMoreAfter" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextBefore" } }, - { keys: '', type: 'action', action: 'aceCommand', actionArgs: { name: "selectNextAfter" } } - ); - actions.aceCommand = function(cm, actionArgs, vim) { - cm.vimCmd = actionArgs; - if (cm.ace.inVirtualSelectionMode) - cm.ace.on("beforeEndOperation", delayedExecAceCommand); - else - delayedExecAceCommand(null, cm.ace); - }; - function delayedExecAceCommand(op, ace) { - ace.off("beforeEndOperation", delayedExecAceCommand); - var cmd = ace.state.cm.vimCmd; - if (cmd) { - ace.execCommand(cmd.exec ? cmd : cmd.name, cmd.args); - } - ace.curOp = ace.prevOp; - } - actions.fold = function(cm, actionArgs, vim) { - cm.ace.execCommand(['toggleFoldWidget', 'toggleFoldWidget', 'foldOther', 'unfoldall' - ][(actionArgs.all ? 2 : 0) + (actionArgs.open ? 1 : 0)]); - }, - exports.handler.defaultKeymap = defaultKeymap; - exports.handler.actions = actions; - exports.Vim = Vim; - - Vim.map("Y", "yy", "normal"); + handleKeyboard: function(data, hashId, key, keyCode, e) { + // ignore command keys (shift, ctrl etc.) + if (hashId != 0 && (key == "" || key == "\x00")) + return null; + + var editor = data.editor; + + if (hashId == 1) + key = "ctrl-" + key; + if (key == "ctrl-c") { + if (!useragent.isMac && editor.getCopyText()) { + editor.once("copy", function() { + if (data.state == "start") + coreCommands.stop.exec(editor); + else + editor.selection.clearSelection(); + }); + return {command: "null", passEvent: true}; + } + return {command: coreCommands.stop}; + } else if ((key == "esc" && hashId == 0) || key == "ctrl-[") { + return {command: coreCommands.stop}; + } else if (data.state == "start") { + if (useragent.isMac && this.handleMacRepeat(data, hashId, key)) { + hashId = -1; + key = data.inputChar; + } + + if (hashId == -1 || hashId == 1 || hashId == 0 && key.length > 1) { + if (cmds.inputBuffer.idle && startCommands[key]) + return startCommands[key]; + cmds.inputBuffer.push(editor, key); + return {command: "null", passEvent: false}; + } // if no modifier || shift: wait for input. + else if (key.length == 1 && (hashId == 0 || hashId == 4)) { + return {command: "null", passEvent: true}; + } else if (key == "esc" && hashId == 0) { + return {command: coreCommands.stop}; + } + } else { + if (key == "ctrl-w") { + return {command: "removewordleft"}; + } + } + }, + + attach: function(editor) { + editor.on("click", exports.onCursorMove); + if (util.currentMode !== "insert") + cmds.coreCommands.stop.exec(editor); + editor.$vimModeHandler = this; + + this.updateMacCompositionHandlers(editor, true); + }, + + detach: function(editor) { + editor.removeListener("click", exports.onCursorMove); + util.noMode(editor); + util.currentMode = "normal"; + this.updateMacCompositionHandlers(editor, false); + }, + + actions: cmds.actions, + getStatusText: function() { + if (util.currentMode == "insert") + return "INSERT"; + if (util.onVisualMode) + return (util.onVisualLineMode ? "VISUAL LINE " : "VISUAL ") + cmds.inputBuffer.status; + return cmds.inputBuffer.status; + } +}; + + +exports.onCursorMove = function(e) { + cmds.onCursorMove(e.editor, e); + exports.onCursorMove.scheduled = false; +}; + }); diff --git a/lib/ace/keyboard/vim/commands.js b/lib/ace/keyboard/vim/commands.js new file mode 100644 index 00000000..dd3357d6 --- /dev/null +++ b/lib/ace/keyboard/vim/commands.js @@ -0,0 +1,613 @@ +/* ***** 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) { + +"never use strict"; + +var lang = require("../../lib/lang"); +var util = require("./maps/util"); +var motions = require("./maps/motions"); +var operators = require("./maps/operators"); +var alias = require("./maps/aliases"); +var registers = require("./registers"); + +var NUMBER = 1; +var OPERATOR = 2; +var MOTION = 3; +var ACTION = 4; +var HMARGIN = 8; // Minimum amount of line separation between margins; + +var repeat = function repeat(fn, count, args) { + while (0 < count--) + fn.apply(this, args); +}; + +var ensureScrollMargin = function(editor) { + var renderer = editor.renderer; + var pos = renderer.$cursorLayer.getPixelPosition(); + + var top = pos.top; + + var margin = HMARGIN * renderer.layerConfig.lineHeight; + if (2 * margin > renderer.$size.scrollerHeight) + margin = renderer.$size.scrollerHeight / 2; + + if (renderer.scrollTop > top - margin) { + renderer.session.setScrollTop(top - margin); + } + + if (renderer.scrollTop + renderer.$size.scrollerHeight < top + margin + renderer.lineHeight) { + renderer.session.setScrollTop(top + margin + renderer.lineHeight - renderer.$size.scrollerHeight); + } +}; + +var actions = exports.actions = { + "z": { + param: true, + fn: function(editor, range, count, param) { + switch (param) { + case "z": + editor.renderer.alignCursor(null, 0.5); + break; + case "t": + editor.renderer.alignCursor(null, 0); + break; + case "b": + editor.renderer.alignCursor(null, 1); + break; + case "c": + editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}}); + break; + case "o": + editor.session.onFoldWidgetClick(range.start.row, {domEvent:{target :{}}}); + break; + case "C": + editor.session.foldAll(); + break; + case "O": + editor.session.unfold(); + break; + } + } + }, + "r": { + param: true, + fn: function(editor, range, count, param) { + if (param && param.length) { + if (param.length > 1) + param = param == "return" ? "\n" : param == "tab" ? "\t" : param; + repeat(function() { editor.insert(param); }, count || 1); + editor.navigateLeft(); + } + } + }, + "R": { + fn: function(editor, range, count, param) { + util.insertMode(editor); + editor.setOverwrite(true); + } + }, + "~": { + fn: function(editor, range, count) { + repeat(function() { + var range = editor.selection.getRange(); + if (range.isEmpty()) + range.end.column++; + var text = editor.session.getTextRange(range); + var toggled = text.toUpperCase(); + if (toggled == text) + editor.navigateRight(); + else + editor.session.replace(range, toggled); + }, count || 1); + } + }, + "*": { + fn: function(editor, range, count, param) { + editor.selection.selectWord(); + editor.findNext(); + ensureScrollMargin(editor); + var r = editor.selection.getRange(); + editor.selection.setSelectionRange(r, true); + } + }, + "#": { + fn: function(editor, range, count, param) { + editor.selection.selectWord(); + editor.findPrevious(); + ensureScrollMargin(editor); + var r = editor.selection.getRange(); + editor.selection.setSelectionRange(r, true); + } + }, + "m": { + param: true, + fn: function(editor, range, count, param) { + var s = editor.session; + var markers = s.vimMarkers || (s.vimMarkers = {}); + var c = editor.getCursorPosition(); + if (!markers[param]) { + markers[param] = editor.session.doc.createAnchor(c); + } + markers[param].setPosition(c.row, c.column, true); + } + }, + "n": { + fn: function(editor, range, count, param) { + var options = editor.getLastSearchOptions(); + options.backwards = false; + + editor.selection.moveCursorRight(); + editor.selection.clearSelection(); + editor.findNext(options); + + ensureScrollMargin(editor); + var r = editor.selection.getRange(); + r.end.row = r.start.row; + r.end.column = r.start.column; + editor.selection.setSelectionRange(r, true); + } + }, + "N": { + fn: function(editor, range, count, param) { + var options = editor.getLastSearchOptions(); + options.backwards = true; + + editor.findPrevious(options); + ensureScrollMargin(editor); + var r = editor.selection.getRange(); + r.end.row = r.start.row; + r.end.column = r.start.column; + editor.selection.setSelectionRange(r, true); + } + }, + "v": { + fn: function(editor, range, count, param) { + editor.selection.selectRight(); + util.visualMode(editor, false); + }, + acceptsMotion: true + }, + "V": { + fn: function(editor, range, count, param) { + //editor.selection.selectLine(); + //editor.selection.selectLeft(); + var row = editor.getCursorPosition().row; + editor.selection.clearSelection(); + editor.selection.moveCursorTo(row, 0); + editor.selection.selectLineEnd(); + editor.selection.visualLineStart = row; + + util.visualMode(editor, true); + }, + acceptsMotion: true + }, + "Y": { + fn: function(editor, range, count, param) { + util.copyLine(editor); + } + }, + "p": { + fn: function(editor, range, count, param) { + var defaultReg = registers._default; + + editor.setOverwrite(false); + if (defaultReg.isLine) { + var pos = editor.getCursorPosition(); + pos.column = editor.session.getLine(pos.row).length; + var text = lang.stringRepeat("\n" + defaultReg.text, count || 1); + editor.session.insert(pos, text); + editor.moveCursorTo(pos.row + 1, 0); + } + else { + editor.navigateRight(); + editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); + editor.navigateLeft(); + } + editor.setOverwrite(true); + editor.selection.clearSelection(); + } + }, + "P": { + fn: function(editor, range, count, param) { + var defaultReg = registers._default; + editor.setOverwrite(false); + + if (defaultReg.isLine) { + var pos = editor.getCursorPosition(); + pos.column = 0; + var text = lang.stringRepeat(defaultReg.text + "\n", count || 1); + editor.session.insert(pos, text); + editor.moveCursorToPosition(pos); + } + else { + editor.insert(lang.stringRepeat(defaultReg.text, count || 1)); + } + editor.setOverwrite(true); + editor.selection.clearSelection(); + } + }, + "J": { + fn: function(editor, range, count, param) { + var session = editor.session; + range = editor.getSelectionRange(); + var pos = {row: range.start.row, column: range.start.column}; + count = count || range.end.row - range.start.row; + var maxRow = Math.min(pos.row + (count || 1), session.getLength() - 1); + + range.start.column = session.getLine(pos.row).length; + range.end.column = session.getLine(maxRow).length; + range.end.row = maxRow; + + var text = ""; + for (var i = pos.row; i < maxRow; i++) { + var nextLine = session.getLine(i + 1); + text += " " + /^\s*(.*)$/.exec(nextLine)[1] || ""; + } + + session.replace(range, text); + editor.moveCursorTo(pos.row, pos.column); + } + }, + "u": { + fn: function(editor, range, count, param) { + count = parseInt(count || 1, 10); + for (var i = 0; i < count; i++) { + editor.undo(); + } + editor.selection.clearSelection(); + } + }, + "ctrl-r": { + fn: function(editor, range, count, param) { + count = parseInt(count || 1, 10); + for (var i = 0; i < count; i++) { + editor.redo(); + } + editor.selection.clearSelection(); + } + }, + ":": { + fn: function(editor, range, count, param) { + var val = ":"; + if (count > 1) + val = ".,.+" + count + val; + if (editor.showCommandLine) + editor.showCommandLine(val); + } + }, + "/": { + fn: function(editor, range, count, param) { + if (editor.showCommandLine) + editor.showCommandLine("/"); + } + }, + "?": { + fn: function(editor, range, count, param) { + if (editor.showCommandLine) + editor.showCommandLine("?"); + } + }, + ".": { + fn: function(editor, range, count, param) { + util.onInsertReplaySequence = inputBuffer.lastInsertCommands; + var previous = inputBuffer.previous; + if (previous) // If there is a previous action + inputBuffer.exec(editor, previous.action, previous.param); + } + }, + "ctrl-x": { + fn: function(editor, range, count, param) { + editor.modifyNumber(-(count || 1)); + } + }, + "ctrl-a": { + fn: function(editor, range, count, param) { + editor.modifyNumber(count || 1); + } + } +}; + +var inputBuffer = exports.inputBuffer = { + accepting: [NUMBER, OPERATOR, MOTION, ACTION], + currentCmd: null, + //currentMode: 0, + currentCount: "", + status: "", + + // Types + operator: null, + motion: null, + + lastInsertCommands: [], + + push: function(editor, ch, keyId) { + var status = this.status; + var isKeyHandled = true; + this.idle = false; + var wObj = this.waitingForParam; + if (/^numpad\d+$/i.test(ch)) + ch = ch.substr(6); + + if (wObj) { + this.exec(editor, wObj, ch); + } + // If input is a number (that doesn't start with 0) + else if (!(ch === "0" && !this.currentCount.length) && + (/^\d+$/.test(ch) && this.isAccepting(NUMBER))) { + // Assuming that ch is always of type String, and not Number + this.currentCount += ch; + this.currentCmd = NUMBER; + this.accepting = [NUMBER, OPERATOR, MOTION, ACTION]; + } + else if (!this.operator && this.isAccepting(OPERATOR) && operators[ch]) { + this.operator = { + ch: ch, + count: this.getCount() + }; + this.currentCmd = OPERATOR; + this.accepting = [NUMBER, MOTION, ACTION]; + this.exec(editor, { operator: this.operator }); + } + else if (motions[ch] && this.isAccepting(MOTION)) { + this.currentCmd = MOTION; + + var ctx = { + operator: this.operator, + motion: { + ch: ch, + count: this.getCount() + } + }; + + if (motions[ch].param) + this.waitForParam(ctx); + else + this.exec(editor, ctx); + } + else if (alias[ch] && this.isAccepting(MOTION)) { + alias[ch].operator.count = this.getCount(); + this.exec(editor, alias[ch]); + } + else if (actions[ch] && this.isAccepting(ACTION)) { + var actionObj = { + action: { + fn: actions[ch].fn, + count: this.getCount() + } + }; + + if (actions[ch].param) { + this.waitForParam(actionObj); + } + else { + this.exec(editor, actionObj); + } + + if (actions[ch].acceptsMotion) + this.idle = false; + } + else if (this.operator) { + this.operator.count = this.getCount(); + this.exec(editor, { operator: this.operator }, ch); + } + else { + isKeyHandled = ch.length == 1; + this.reset(); + } + + if (this.waitingForParam || this.motion || this.operator) { + this.status += ch; + } else if (this.currentCount) { + this.status = this.currentCount; + } else if (this.status) { + this.status = ""; + } + if (this.status != status) + editor._emit("changeStatus"); + return isKeyHandled; + }, + + waitForParam: function(cmd) { + this.waitingForParam = cmd; + }, + + getCount: function() { + var count = this.currentCount; + this.currentCount = ""; + return count && parseInt(count, 10); + }, + + exec: function(editor, action, param) { + var m = action.motion; + var o = action.operator; + var a = action.action; + + if (!param) + param = action.param; + + if (o) { + this.previous = { + action: action, + param: param + }; + } + + if (o && !editor.selection.isEmpty()) { + if (operators[o.ch].selFn) { + operators[o.ch].selFn(editor, editor.getSelectionRange(), o.count, param); + this.reset(); + } + return; + } + + // There is an operator, but no motion or action. We try to pass the + // current ch to the operator to see if it responds to it (an example + // of this is the 'dd' operator). + else if (!m && !a && o && param) { + operators[o.ch].fn(editor, null, o.count, param); + this.reset(); + } + else if (m) { + var run = function(fn) { + if (fn && typeof fn === "function") { // There should always be a motion + if (m.count && !motionObj.handlesCount) + repeat(fn, m.count, [editor, null, m.count, param]); + else + fn(editor, null, m.count, param); + } + }; + + var motionObj = motions[m.ch]; + var selectable = motionObj.sel; + + if (!o) { + if ((util.onVisualMode || util.onVisualLineMode) && selectable) + run(motionObj.sel); + else + run(motionObj.nav); + } + else if (selectable) { + repeat(function() { + run(motionObj.sel); + operators[o.ch].fn(editor, editor.getSelectionRange(), o.count, param); + }, o.count || 1); + } + this.reset(); + } + else if (a) { + a.fn(editor, editor.getSelectionRange(), a.count, param); + this.reset(); + } + handleCursorMove(editor); + }, + + isAccepting: function(type) { + return this.accepting.indexOf(type) !== -1; + }, + + reset: function() { + this.operator = null; + this.motion = null; + this.currentCount = ""; + this.status = ""; + this.accepting = [NUMBER, OPERATOR, MOTION, ACTION]; + this.idle = true; + this.waitingForParam = null; + } +}; + +function setPreviousCommand(fn) { + inputBuffer.previous = { action: { action: { fn: fn } } }; +} + +exports.coreCommands = { + start: { + exec: function start(editor) { + util.insertMode(editor); + setPreviousCommand(start); + } + }, + startBeginning: { + exec: function startBeginning(editor) { + editor.navigateLineStart(); + util.insertMode(editor); + setPreviousCommand(startBeginning); + } + }, + // Stop Insert mode as soon as possible. Works like typing in + // insert mode. + stop: { + exec: function stop(editor) { + inputBuffer.reset(); + util.onVisualMode = false; + util.onVisualLineMode = false; + inputBuffer.lastInsertCommands = util.normalMode(editor); + } + }, + append: { + exec: function append(editor) { + var pos = editor.getCursorPosition(); + var lineLen = editor.session.getLine(pos.row).length; + if (lineLen) + editor.navigateRight(); + util.insertMode(editor); + setPreviousCommand(append); + } + }, + appendEnd: { + exec: function appendEnd(editor) { + editor.navigateLineEnd(); + util.insertMode(editor); + setPreviousCommand(appendEnd); + } + } +}; + +var handleCursorMove = exports.onCursorMove = function(editor, e) { + if (util.currentMode === 'insert' || handleCursorMove.running) + return; + else if(!editor.selection.isEmpty()) { + handleCursorMove.running = true; + if (util.onVisualLineMode) { + var originRow = editor.selection.visualLineStart; + var cursorRow = editor.getCursorPosition().row; + if(originRow <= cursorRow) { + var endLine = editor.session.getLine(cursorRow); + editor.selection.clearSelection(); + editor.selection.moveCursorTo(originRow, 0); + editor.selection.selectTo(cursorRow, endLine.length); + } else { + var endLine = editor.session.getLine(originRow); + editor.selection.clearSelection(); + editor.selection.moveCursorTo(originRow, endLine.length); + editor.selection.selectTo(cursorRow, 0); + } + } + handleCursorMove.running = false; + return; + } + else { + if (e && (util.onVisualLineMode || util.onVisualMode)) { + editor.selection.clearSelection(); + util.normalMode(editor); + } + + handleCursorMove.running = true; + var pos = editor.getCursorPosition(); + var lineLen = editor.session.getLine(pos.row).length; + + if (lineLen && pos.column === lineLen) + editor.navigateLeft(); + handleCursorMove.running = false; + } +}; +}); diff --git a/lib/ace/mode/dockerfile_highlight_rules.js b/lib/ace/keyboard/vim/maps/aliases.js similarity index 65% rename from lib/ace/mode/dockerfile_highlight_rules.js rename to lib/ace/keyboard/vim/maps/aliases.js index c94ed650..1a5f32f7 100644 --- a/lib/ace/mode/dockerfile_highlight_rules.js +++ b/lib/ace/keyboard/vim/maps/aliases.js @@ -27,31 +27,68 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * ***** END LICENSE BLOCK ***** */ + +"use strict" define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var ShHighlightRules = require("./sh_highlight_rules").ShHighlightRules; - -var DockerfileHighlightRules = function() { - ShHighlightRules.call(this); - - var startRules = this.$rules.start; - for (var i = 0; i < startRules.length; i++) { - if (startRules[i].token == "variable.language") { - startRules.splice(i, 0, { - token: "constant.language", - regex: "(?:^(?:FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|COPY)\\b)", - caseInsensitive: true - }); - break; +module.exports = { + "x": { + operator: { + ch: "d", + count: 1 + }, + motion: { + ch: "l", + count: 1 } + }, + "X": { + operator: { + ch: "d", + count: 1 + }, + motion: { + ch: "h", + count: 1 + } + }, + "D": { + operator: { + ch: "d", + count: 1 + }, + motion: { + ch: "$", + count: 1 + } + }, + "C": { + operator: { + ch: "c", + count: 1 + }, + motion: { + ch: "$", + count: 1 + } + }, + "s": { + operator: { + ch: "c", + count: 1 + }, + motion: { + ch: "l", + count: 1 + } + }, + "S": { + operator: { + ch: "c", + count: 1 + }, + param: "c" } - }; - -oop.inherits(DockerfileHighlightRules, ShHighlightRules); - -exports.DockerfileHighlightRules = DockerfileHighlightRules; }); + diff --git a/lib/ace/keyboard/vim/maps/motions.js b/lib/ace/keyboard/vim/maps/motions.js new file mode 100644 index 00000000..5fdfe955 --- /dev/null +++ b/lib/ace/keyboard/vim/maps/motions.js @@ -0,0 +1,664 @@ +/* ***** 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 util = require("./util"); + +var keepScrollPosition = function(editor, fn) { + var scrollTopRow = editor.renderer.getScrollTopRow(); + var initialRow = editor.getCursorPosition().row; + var diff = initialRow - scrollTopRow; + fn && fn.call(editor); + editor.renderer.scrollToRow(editor.getCursorPosition().row - diff); +}; + +function Motion(m) { + if (typeof m == "function") { + var getPos = m; + m = this; + } else { + var getPos = m.getPos; + } + m.nav = function(editor, range, count, param) { + var a = getPos(editor, range, count, param, false); + if (!a) + return; + editor.clearSelection(); + editor.moveCursorTo(a.row, a.column); + }; + m.sel = function(editor, range, count, param) { + var a = getPos(editor, range, count, param, true); + if (!a) + return; + editor.selection.selectTo(a.row, a.column); + }; + return m; +} + +var nonWordRe = /[\s.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/; +var wordSeparatorRe = /[.\/\\()\"'-:,.;<>~!@#$%^&*|+=\[\]{}`~?]/; +var whiteRe = /\s/; +var StringStream = function(editor, cursor) { + var sel = editor.selection; + this.range = sel.getRange(); + cursor = cursor || sel.selectionLead; + this.row = cursor.row; + this.col = cursor.column; + var line = editor.session.getLine(this.row); + var maxRow = editor.session.getLength(); + this.ch = line[this.col] || '\n'; + this.skippedLines = 0; + + this.next = function() { + this.ch = line[++this.col] || this.handleNewLine(1); + //this.debug() + return this.ch; + }; + this.prev = function() { + this.ch = line[--this.col] || this.handleNewLine(-1); + //this.debug() + return this.ch; + }; + this.peek = function(dir) { + var ch = line[this.col + dir]; + if (ch) + return ch; + if (dir == -1) + return '\n'; + if (this.col == line.length - 1) + return '\n'; + return editor.session.getLine(this.row + 1)[0] || '\n'; + }; + + this.handleNewLine = function(dir) { + if (dir == 1){ + if (this.col == line.length) + return '\n'; + if (this.row == maxRow - 1) + return ''; + this.col = 0; + this.row ++; + line = editor.session.getLine(this.row); + this.skippedLines++; + return line[0] || '\n'; + } + if (dir == -1) { + if (this.row === 0) + return ''; + this.row --; + line = editor.session.getLine(this.row); + this.col = line.length; + this.skippedLines--; + return '\n'; + } + }; + this.debug = function() { + console.log(line.substring(0, this.col)+'|'+this.ch+'\''+this.col+'\''+line.substr(this.col+1)); + }; +}; + +var Search = require("../../../search").Search; +var search = new Search(); + +function find(editor, needle, dir) { + search.$options.needle = needle; + search.$options.backwards = dir == -1; + return search.find(editor.session); +} + +var Range = require("../../../range").Range; + +var LAST_SEARCH_MOTION = {}; + +module.exports = { + "w": new Motion(function(editor) { + var str = new StringStream(editor); + + if (str.ch && wordSeparatorRe.test(str.ch)) { + while (str.ch && wordSeparatorRe.test(str.ch)) + str.next(); + } else { + while (str.ch && !nonWordRe.test(str.ch)) + str.next(); + } + while (str.ch && whiteRe.test(str.ch) && str.skippedLines < 2) + str.next(); + + str.skippedLines == 2 && str.prev(); + return {column: str.col, row: str.row}; + }), + "W": new Motion(function(editor) { + var str = new StringStream(editor); + while(str.ch && !(whiteRe.test(str.ch) && !whiteRe.test(str.peek(1))) && str.skippedLines < 2) + str.next(); + if (str.skippedLines == 2) + str.prev(); + else + str.next(); + + return {column: str.col, row: str.row}; + }), + "b": new Motion(function(editor) { + var str = new StringStream(editor); + + str.prev(); + while (str.ch && whiteRe.test(str.ch) && str.skippedLines > -2) + str.prev(); + + if (str.ch && wordSeparatorRe.test(str.ch)) { + while (str.ch && wordSeparatorRe.test(str.ch)) + str.prev(); + } else { + while (str.ch && !nonWordRe.test(str.ch)) + str.prev(); + } + str.ch && str.next(); + return {column: str.col, row: str.row}; + }), + "B": new Motion(function(editor) { + var str = new StringStream(editor); + str.prev(); + while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(-1))) && str.skippedLines > -2) + str.prev(); + + if (str.skippedLines == -2) + str.next(); + + return {column: str.col, row: str.row}; + }), + "e": new Motion(function(editor) { + var str = new StringStream(editor); + + str.next(); + while (str.ch && whiteRe.test(str.ch)) + str.next(); + + if (str.ch && wordSeparatorRe.test(str.ch)) { + while (str.ch && wordSeparatorRe.test(str.ch)) + str.next(); + } else { + while (str.ch && !nonWordRe.test(str.ch)) + str.next(); + } + str.ch && str.prev(); + return {column: str.col, row: str.row}; + }), + "E": new Motion(function(editor) { + var str = new StringStream(editor); + str.next(); + while(str.ch && !(!whiteRe.test(str.ch) && whiteRe.test(str.peek(1)))) + str.next(); + + return {column: str.col, row: str.row}; + }), + + "l": { + nav: function(editor) { + var pos = editor.getCursorPosition(); + var col = pos.column; + var lineLen = editor.session.getLine(pos.row).length; + if (lineLen && col !== lineLen) + editor.navigateRight(); + }, + sel: function(editor) { + var pos = editor.getCursorPosition(); + var col = pos.column; + var lineLen = editor.session.getLine(pos.row).length; + + // Solving the behavior at the end of the line due to the + // different 0 index-based colum positions in ACE. + if (lineLen && col !== lineLen) //In selection mode you can select the newline + editor.selection.selectRight(); + } + }, + "h": { + nav: function(editor) { + var pos = editor.getCursorPosition(); + if (pos.column > 0) + editor.navigateLeft(); + }, + sel: function(editor) { + var pos = editor.getCursorPosition(); + if (pos.column > 0) + editor.selection.selectLeft(); + } + }, + "H": { + nav: function(editor) { + var row = editor.renderer.getScrollTopRow(); + editor.moveCursorTo(row); + }, + sel: function(editor) { + var row = editor.renderer.getScrollTopRow(); + editor.selection.selectTo(row); + } + }, + "M": { + nav: function(editor) { + var topRow = editor.renderer.getScrollTopRow(); + var bottomRow = editor.renderer.getScrollBottomRow(); + var row = topRow + ((bottomRow - topRow) / 2); + editor.moveCursorTo(row); + }, + sel: function(editor) { + var topRow = editor.renderer.getScrollTopRow(); + var bottomRow = editor.renderer.getScrollBottomRow(); + var row = topRow + ((bottomRow - topRow) / 2); + editor.selection.selectTo(row); + } + }, + "L": { + nav: function(editor) { + var row = editor.renderer.getScrollBottomRow(); + editor.moveCursorTo(row); + }, + sel: function(editor) { + var row = editor.renderer.getScrollBottomRow(); + editor.selection.selectTo(row); + } + }, + "k": { + nav: function(editor) { + editor.navigateUp(); + }, + sel: function(editor) { + editor.selection.selectUp(); + } + }, + "j": { + nav: function(editor) { + editor.navigateDown(); + }, + sel: function(editor) { + editor.selection.selectDown(); + } + }, + + "i": { + param: true, + sel: function(editor, range, count, param) { + switch (param) { + case "w": + editor.selection.selectWord(); + break; + case "W": + editor.selection.selectAWord(); + break; + case "(": + case "{": + case "[": + var cursor = editor.getCursorPosition(); + var end = editor.session.$findClosingBracket(param, cursor, /paren/); + if (!end) + return; + var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, /paren/); + if (!start) + return; + start.column ++; + editor.selection.setSelectionRange(Range.fromPoints(start, end)); + break; + case "'": + case '"': + case "/": + var end = find(editor, param, 1); + if (!end) + return; + var start = find(editor, param, -1); + if (!start) + return; + editor.selection.setSelectionRange(Range.fromPoints(start.end, end.start)); + break; + } + } + }, + "a": { + param: true, + sel: function(editor, range, count, param) { + switch (param) { + case "w": + editor.selection.selectAWord(); + break; + case "W": + editor.selection.selectAWord(); + break; + case "(": + case "{": + case "[": + var cursor = editor.getCursorPosition(); + var end = editor.session.$findClosingBracket(param, cursor, "paren"); + if (!end) + return; + var start = editor.session.$findOpeningBracket(editor.session.$brackets[param], cursor, "paren"); + if (!start) + return; + end.column ++; + editor.selection.setSelectionRange(Range.fromPoints(start, end)); + break; + case "'": + case "\"": + case "/": + var end = find(editor, param, 1); + if (!end) + return; + var start = find(editor, param, -1); + if (!start) + return; + end.column ++; + editor.selection.setSelectionRange(Range.fromPoints(start.start, end.end)); + break; + } + } + }, + + "f": new Motion({ + param: true, + handlesCount: true, + getPos: function(editor, range, count, param, isSel, isRepeat) { + if (!isRepeat) + LAST_SEARCH_MOTION = {ch: "f", param: param}; + var cursor = editor.getCursorPosition(); + var column = util.getRightNthChar(editor, cursor, param, count || 1); + + if (typeof column === "number") { + cursor.column += column + (isSel ? 2 : 1); + return cursor; + } + } + }), + "F": new Motion({ + param: true, + handlesCount: true, + getPos: function(editor, range, count, param, isSel, isRepeat) { + if (!isRepeat) + LAST_SEARCH_MOTION = {ch: "F", param: param}; + var cursor = editor.getCursorPosition(); + var column = util.getLeftNthChar(editor, cursor, param, count || 1); + + if (typeof column === "number") { + cursor.column -= column + 1; + return cursor; + } + } + }), + "t": new Motion({ + param: true, + handlesCount: true, + getPos: function(editor, range, count, param, isSel, isRepeat) { + if (!isRepeat) + LAST_SEARCH_MOTION = {ch: "t", param: param}; + var cursor = editor.getCursorPosition(); + var column = util.getRightNthChar(editor, cursor, param, count || 1); + + if (isRepeat && column == 0 && !(count > 1)) + var column = util.getRightNthChar(editor, cursor, param, 2); + + if (typeof column === "number") { + cursor.column += column + (isSel ? 1 : 0); + return cursor; + } + } + }), + "T": new Motion({ + param: true, + handlesCount: true, + getPos: function(editor, range, count, param, isSel, isRepeat) { + if (!isRepeat) + LAST_SEARCH_MOTION = {ch: "T", param: param}; + var cursor = editor.getCursorPosition(); + var column = util.getLeftNthChar(editor, cursor, param, count || 1); + + if (isRepeat && column == 0 && !(count > 1)) + var column = util.getLeftNthChar(editor, cursor, param, 2); + + if (typeof column === "number") { + cursor.column -= column; + return cursor; + } + } + }), + ";": new Motion({ + handlesCount: true, + getPos: function(editor, range, count, param, isSel) { + var ch = LAST_SEARCH_MOTION.ch; + if (!ch) + return; + return module.exports[ch].getPos( + editor, range, count, LAST_SEARCH_MOTION.param, isSel, true + ); + } + }), + ",": new Motion({ + handlesCount: true, + getPos: function(editor, range, count, param, isSel) { + var ch = LAST_SEARCH_MOTION.ch; + if (!ch) + return; + var up = ch.toUpperCase(); + ch = ch === up ? ch.toLowerCase() : up; + + return module.exports[ch].getPos( + editor, range, count, LAST_SEARCH_MOTION.param, isSel, true + ); + } + }), + + "^": { + nav: function(editor) { + editor.navigateLineStart(); + }, + sel: function(editor) { + editor.selection.selectLineStart(); + } + }, + "$": { + nav: function(editor) { + editor.navigateLineEnd(); + }, + sel: function(editor) { + editor.selection.selectLineEnd(); + } + }, + "0": new Motion(function(ed) { + return {row: ed.selection.lead.row, column: 0}; + }), + "G": { + nav: function(editor, range, count, param) { + if (!count && count !== 0) { // Stupid JS + count = editor.session.getLength(); + } + editor.gotoLine(count); + }, + sel: function(editor, range, count, param) { + if (!count && count !== 0) { // Stupid JS + count = editor.session.getLength(); + } + editor.selection.selectTo(count, 0); + } + }, + "g": { + param: true, + nav: function(editor, range, count, param) { + switch(param) { + case "m": + console.log("Middle line"); + break; + case "e": + console.log("End of prev word"); + break; + case "g": + editor.gotoLine(count || 0); + case "u": + editor.gotoLine(count || 0); + case "U": + editor.gotoLine(count || 0); + } + }, + sel: function(editor, range, count, param) { + switch(param) { + case "m": + console.log("Middle line"); + break; + case "e": + console.log("End of prev word"); + break; + case "g": + editor.selection.selectTo(count || 0, 0); + } + } + }, + "o": { + nav: function(editor, range, count, param) { + count = count || 1; + var content = ""; + while (0 < count--) + content += "\n"; + + if (content.length) { + editor.navigateLineEnd() + editor.insert(content); + util.insertMode(editor); + } + } + }, + "O": { + nav: function(editor, range, count, param) { + var row = editor.getCursorPosition().row; + count = count || 1; + var content = ""; + while (0 < count--) + content += "\n"; + + if (content.length) { + if(row > 0) { + editor.navigateUp(); + editor.navigateLineEnd() + editor.insert(content); + } else { + editor.session.insert({row: 0, column: 0}, content); + editor.navigateUp(); + } + util.insertMode(editor); + } + } + }, + "%": new Motion(function(editor){ + var brRe = /[\[\]{}()]/g; + var cursor = editor.getCursorPosition(); + var ch = editor.session.getLine(cursor.row)[cursor.column]; + if (!brRe.test(ch)) { + var range = find(editor, brRe); + if (!range) + return; + cursor = range.start; + } + var match = editor.session.findMatchingBracket({ + row: cursor.row, + column: cursor.column + 1 + }); + + return match; + }), + "{": new Motion(function(ed) { + var session = ed.session; + var row = session.selection.lead.row; + while(row > 0 && !/\S/.test(session.getLine(row))) + row--; + while(/\S/.test(session.getLine(row))) + row--; + return {column: 0, row: row}; + }), + "}": new Motion(function(ed) { + var session = ed.session; + var l = session.getLength(); + var row = session.selection.lead.row; + while(row < l && !/\S/.test(session.getLine(row))) + row++; + while(/\S/.test(session.getLine(row))) + row++; + return {column: 0, row: row}; + }), + "ctrl-d": { + nav: function(editor, range, count, param) { + editor.selection.clearSelection(); + keepScrollPosition(editor, editor.gotoPageDown); + }, + sel: function(editor, range, count, param) { + keepScrollPosition(editor, editor.selectPageDown); + } + }, + "ctrl-u": { + nav: function(editor, range, count, param) { + editor.selection.clearSelection(); + keepScrollPosition(editor, editor.gotoPageUp); + }, + sel: function(editor, range, count, param) { + keepScrollPosition(editor, editor.selectPageUp); + } + }, + "`": new Motion({ + param: true, + handlesCount: true, + getPos: function(editor, range, count, param, isSel) { + var s = editor.session; + var marker = s.vimMarkers && s.vimMarkers[param]; + if (marker) { + return marker.getPosition(); + } + } + }), + "'": new Motion({ + param: true, + handlesCount: true, + getPos: function(editor, range, count, param, isSel) { + var s = editor.session; + var marker = s.vimMarkers && s.vimMarkers[param]; + if (marker) { + var pos = marker.getPosition(); + var line = editor.session.getLine(pos.row); + pos.column = line.search(/\S/); + if (pos.column == -1) + pos.column = line.length; + return pos; + } + } + }) +}; + +module.exports.backspace = module.exports.left = module.exports.h; +module.exports.space = module.exports['return'] = module.exports.right = module.exports.l; +module.exports.up = module.exports.k; +module.exports.down = module.exports.j; +module.exports.pagedown = module.exports["ctrl-d"]; +module.exports.pageup = module.exports["ctrl-u"]; + +}); diff --git a/lib/ace/keyboard/vim/maps/operators.js b/lib/ace/keyboard/vim/maps/operators.js new file mode 100644 index 00000000..067562a0 --- /dev/null +++ b/lib/ace/keyboard/vim/maps/operators.js @@ -0,0 +1,195 @@ +/* ***** 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 util = require("./util"); +var registers = require("../registers"); + +module.exports = { + "d": { + selFn: function(editor, range, count, param) { + registers._default.text = editor.getCopyText(); + registers._default.isLine = util.onVisualLineMode; + if(util.onVisualLineMode) + editor.removeLines(); + else + editor.session.remove(range); + util.normalMode(editor); + }, + fn: function(editor, range, count, param) { + count = count || 1; + switch (param) { + case "d": + registers._default.text = ""; + registers._default.isLine = true; + for (var i = 0; i < count; i++) { + editor.selection.selectLine(); + registers._default.text += editor.getCopyText(); + var selRange = editor.getSelectionRange(); + // check if end of the document was reached + if (!selRange.isMultiLine()) { + var row = selRange.start.row - 1; + var col = editor.session.getLine(row).length + selRange.setStart(row, col); + editor.session.remove(selRange); + editor.selection.clearSelection(); + break; + } + editor.session.remove(selRange); + editor.selection.clearSelection(); + } + registers._default.text = registers._default.text.replace(/\n$/, ""); + break; + default: + if (range) { + editor.selection.setSelectionRange(range); + registers._default.text = editor.getCopyText(); + registers._default.isLine = false; + editor.session.remove(range); + editor.selection.clearSelection(); + } + } + } + }, + "c": { + selFn: function(editor, range, count, param) { + editor.session.remove(range); + util.insertMode(editor); + }, + fn: function(editor, range, count, param) { + count = count || 1; + switch (param) { + case "c": + for (var i = 0; i < count; i++) { + editor.removeLines(); + util.insertMode(editor); + } + + break; + default: + if (range) { + + // range.end.column ++; + editor.session.remove(range); + util.insertMode(editor); + } + } + } + }, + "y": { + selFn: function(editor, range, count, param) { + registers._default.text = editor.getCopyText(); + registers._default.isLine = util.onVisualLineMode; + editor.selection.clearSelection(); + util.normalMode(editor); + }, + fn: function(editor, range, count, param) { + count = count || 1; + switch (param) { + case "y": + var pos = editor.getCursorPosition(); + editor.selection.selectLine(); + for (var i = 0; i < count - 1; i++) { + editor.selection.moveCursorDown(); + } + registers._default.text = editor.getCopyText().replace(/\n$/, ""); + editor.selection.clearSelection(); + registers._default.isLine = true; + editor.moveCursorToPosition(pos); + break; + default: + if (range) { + var pos = editor.getCursorPosition(); + editor.selection.setSelectionRange(range); + registers._default.text = editor.getCopyText(); + registers._default.isLine = false; + editor.selection.clearSelection(); + editor.moveCursorTo(pos.row, pos.column); + } + } + } + }, + ">": { + selFn: function(editor, range, count, param) { + count = count || 1; + for (var i = 0; i < count; i++) { + editor.indent(); + } + util.normalMode(editor); + }, + fn: function(editor, range, count, param) { + count = parseInt(count || 1, 10); + switch (param) { + case ">": + var pos = editor.getCursorPosition(); + editor.selection.selectLine(); + for (var i = 0; i < count - 1; i++) { + editor.selection.moveCursorDown(); + } + editor.indent(); + editor.selection.clearSelection(); + editor.moveCursorToPosition(pos); + editor.navigateLineEnd(); + editor.navigateLineStart(); + break; + } + } + }, + "<": { + selFn: function(editor, range, count, param) { + count = count || 1; + for (var i = 0; i < count; i++) { + editor.blockOutdent(); + } + util.normalMode(editor); + }, + fn: function(editor, range, count, param) { + count = count || 1; + switch (param) { + case "<": + var pos = editor.getCursorPosition(); + editor.selection.selectLine(); + for (var i = 0; i < count - 1; i++) { + editor.selection.moveCursorDown(); + } + editor.blockOutdent(); + editor.selection.clearSelection(); + editor.moveCursorToPosition(pos); + editor.navigateLineEnd(); + editor.navigateLineStart(); + break; + } + } + } +}; +}); diff --git a/lib/ace/keyboard/vim/maps/util.js b/lib/ace/keyboard/vim/maps/util.js new file mode 100644 index 00000000..af0e07c7 --- /dev/null +++ b/lib/ace/keyboard/vim/maps/util.js @@ -0,0 +1,134 @@ +define(function(require, exports, module) { +var registers = require("../registers"); + +var dom = require("../../../lib/dom"); +dom.importCssString('.insert-mode .ace_cursor{\ + border-left: 2px solid #333333;\ +}\ +.ace_dark.insert-mode .ace_cursor{\ + border-left: 2px solid #eeeeee;\ +}\ +.normal-mode .ace_cursor{\ + border: 0!important;\ + background-color: red;\ + opacity: 0.5;\ +}', 'vimMode'); + +module.exports = { + onVisualMode: false, + onVisualLineMode: false, + currentMode: 'normal', + noMode: function(editor) { + editor.unsetStyle('insert-mode'); + editor.unsetStyle('normal-mode'); + if (editor.commands.recording) + editor.commands.toggleRecording(editor); + editor.setOverwrite(false); + }, + insertMode: function(editor) { + this.currentMode = 'insert'; + // Switch editor to insert mode + editor.setStyle('insert-mode'); + editor.unsetStyle('normal-mode'); + + editor.setOverwrite(false); + editor.keyBinding.$data.buffer = ""; + editor.keyBinding.$data.state = "insertMode"; + this.onVisualMode = false; + this.onVisualLineMode = false; + if(this.onInsertReplaySequence) { + // Ok, we're apparently replaying ("."), so let's do it + editor.commands.macro = this.onInsertReplaySequence; + editor.commands.replay(editor); + this.onInsertReplaySequence = null; + this.normalMode(editor); + } else { + editor._emit("changeStatus"); + // Record any movements, insertions in insert mode + if(!editor.commands.recording) + editor.commands.toggleRecording(editor); + } + }, + normalMode: function(editor) { + // Switch editor to normal mode + this.currentMode = 'normal'; + + editor.unsetStyle('insert-mode'); + editor.setStyle('normal-mode'); + editor.clearSelection(); + + var pos; + if (!editor.getOverwrite()) { + pos = editor.getCursorPosition(); + if (pos.column > 0) + editor.navigateLeft(); + } + + editor.setOverwrite(true); + editor.keyBinding.$data.buffer = ""; + editor.keyBinding.$data.state = "start"; + this.onVisualMode = false; + this.onVisualLineMode = false; + editor._emit("changeStatus"); + // Save recorded keystrokes + if (editor.commands.recording) { + editor.commands.toggleRecording(editor); + return editor.commands.macro; + } + else { + return []; + } + }, + visualMode: function(editor, lineMode) { + if ( + (this.onVisualLineMode && lineMode) + || (this.onVisualMode && !lineMode) + ) { + this.normalMode(editor); + return; + } + + editor.setStyle('insert-mode'); + editor.unsetStyle('normal-mode'); + + editor._emit("changeStatus"); + if (lineMode) { + this.onVisualLineMode = true; + } else { + this.onVisualMode = true; + this.onVisualLineMode = false; + } + }, + getRightNthChar: function(editor, cursor, ch, n) { + var line = editor.getSession().getLine(cursor.row); + var matches = line.substr(cursor.column + 1).split(ch); + + return n < matches.length ? matches.slice(0, n).join(ch).length : null; + }, + getLeftNthChar: function(editor, cursor, ch, n) { + var line = editor.getSession().getLine(cursor.row); + var matches = line.substr(0, cursor.column).split(ch); + + return n < matches.length ? matches.slice(-1 * n).join(ch).length : null; + }, + toRealChar: function(ch) { + if (ch.length === 1) + return ch; + + if (/^shift-./.test(ch)) + return ch[ch.length - 1].toUpperCase(); + else + return ""; + }, + copyLine: function(editor) { + var pos = editor.getCursorPosition(); + editor.selection.clearSelection(); + editor.moveCursorTo(pos.row, pos.column); + editor.selection.selectLine(); + registers._default.isLine = true; + registers._default.text = editor.getCopyText().replace(/\n$/, ""); + editor.selection.clearSelection(); + editor.moveCursorTo(pos.row, pos.column); + } +}; +}); diff --git a/lib/ace/theme/kuroir.js b/lib/ace/keyboard/vim/registers.js similarity index 89% rename from lib/ace/theme/kuroir.js rename to lib/ace/keyboard/vim/registers.js index cef6a50b..ef929a35 100644 --- a/lib/ace/theme/kuroir.js +++ b/lib/ace/keyboard/vim/registers.js @@ -3,7 +3,7 @@ * * 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 @@ -30,10 +30,13 @@ define(function(require, exports, module) { -exports.isDark = false; -exports.cssClass = "ace-kuroir"; -exports.cssText = require("../requirejs/text!./kuroir.css"); +"never use strict"; + +module.exports = { + _default: { + text: "", + isLine: false + } +}; -var dom = require("../lib/dom"); -dom.importCssString(exports.cssText, exports.cssClass); }); diff --git a/lib/ace/keyboard/vim_test.js b/lib/ace/keyboard/vim_test.js deleted file mode 100644 index 127f0706..00000000 --- a/lib/ace/keyboard/vim_test.js +++ /dev/null @@ -1,4041 +0,0 @@ - -if (typeof process !== "undefined") { - require("amd-loader"); -} - -define(function(require, exports, module) { - -var EditSession = require("./../edit_session").EditSession; -var Editor = require("./../editor").Editor; -var UndoManager = require("./../undomanager").UndoManager; -var MockRenderer = require("./../test/mockrenderer").MockRenderer; -var JavaScriptMode = require("./../mode/javascript").Mode; -var VirtualRenderer = require("./../virtual_renderer").VirtualRenderer; -var assert = require("./../test/assertions"); -var keys = require("./../lib/keys"); -var vim = require("./vim"); - -var el = document.createElement("div"); -el.style.position = "fixed"; -el.style.left = "20px"; -el.style.top = "30px"; -el.style.width = "500px"; -el.style.height = "300px"; -document.body.appendChild(el); - -if (!el.getBoundingClientRect) - return console.log("Skipping test: This test only runs in the browser"); - -var renderer = new VirtualRenderer(el); -editor = new Editor(renderer);//(new MockRenderer()); -editor.session.setUndoManager(new UndoManager()); -editor.session.setUseWorker(false); -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); - editor.setKeyboardHandler(vim.handler); - var cm = editor.state.cm; - cm.setOption("tabSize", opts.tabSize || 4); - cm.setOption("indentUnit", opts.indentUnit || 2); - - cm.setSize = function(w, h) { - var changed = false; - if (w && editor.w != w) { - changed = true; - el.style.width = (editor.w = w) + "px"; - } - if (h && editor.h != h) { - changed = true; - el.style.height = (editor.h = h) + "px"; - } - if (changed) - editor.resize(true); - }; - cm.setSize(500, 300); - return cm; -} -CodeMirror.defineMode = function() {} -for (var key in vim.CodeMirror) - CodeMirror[key] = vim.CodeMirror[key]; -var editor; -var i = 0; -function test(name, fn) { - // if (name != 'vim_search_history') return - // for (i = 0; i < 1000; i++) - // exports["test " + name + i] = fn; // vim_ex_global_confirm - if (i++ < 0 || /- /.test(name)) - exports["test " + name] = function() {}; - else - exports["test " + name] = fn; -} - -vim.CodeMirror.Vim.unmap("Y"); -vim.CodeMirror.Vim.defineEx('write', 'w', function(cm) { - CodeMirror.commands.save(cm); -}); - - - -// cm.setBookmark({ch: 5, line: 0}) -// cm.setBookmark({ch: 4, line: 0}) -// cm.replaceRange("x-", {ch: 4, line: 0}, {ch: 5, line: 0}); [editor.$vimModeHandler.cm.marks[0].find(),editor.$vimModeHandler.cm.marks[1].find()] - -var lineText, verbose, phantom; -var Pos = CodeMirror.Pos; -var place = document.createElement("div"); -var eqPos = assert.deepEqual; -var eq = assert.equal; -var is = assert.ok; - - -var code = '' + -' wOrd1 (#%\n' + -' word3] \n' + -'aopop pop 0 1 2 3 4\n' + -' (a) [b] {c} \n' + -'int getchar(void) {\n' + -' static char buf[BUFSIZ];\n' + -' static char *bufp = buf;\n' + -' if (n == 0) { /* buffer is empty */\n' + -' n = read(0, buf, sizeof buf);\n' + -' bufp = buf;\n' + -' }\n' + -'\n' + -' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + -' \n' + -'}\n'; - -var lines = (function() { - lineText = code.split('\n'); - var ret = []; - for (var i = 0; i < lineText.length; i++) { - ret[i] = { - line: i, - length: lineText[i].length, - lineText: lineText[i], - textStart: /^\s*/.exec(lineText[i])[0].length - }; - } - return ret; -})(); -var endOfDocument = makeCursor(lines.length - 1, - lines[lines.length - 1].length); -var wordLine = lines[0]; -var bigWordLine = lines[1]; -var charLine = lines[2]; -var bracesLine = lines[3]; -var seekBraceLine = lines[4]; - -var word1 = { - start: { line: wordLine.line, ch: 1 }, - end: { line: wordLine.line, ch: 5 } -}; -var word2 = { - start: { line: wordLine.line, ch: word1.end.ch + 2 }, - end: { line: wordLine.line, ch: word1.end.ch + 4 } -}; -var word3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 5 } -}; -var bigWord1 = word1; -var bigWord2 = word2; -var bigWord3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 7 } -}; -var bigWord4 = { - start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, - end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } -}; - -var oChars = [ { line: charLine.line, ch: 1 }, - { line: charLine.line, ch: 3 }, - { line: charLine.line, ch: 7 } ]; -var pChars = [ { line: charLine.line, ch: 2 }, - { line: charLine.line, ch: 4 }, - { line: charLine.line, ch: 6 }, - { line: charLine.line, ch: 8 } ]; -var numChars = [ { line: charLine.line, ch: 10 }, - { line: charLine.line, ch: 12 }, - { line: charLine.line, ch: 14 }, - { line: charLine.line, ch: 16 }, - { line: charLine.line, ch: 18 }]; -var parens1 = { - start: { line: bracesLine.line, ch: 1 }, - end: { line: bracesLine.line, ch: 3 } -}; -var squares1 = { - start: { line: bracesLine.line, ch: 5 }, - end: { line: bracesLine.line, ch: 7 } -}; -var curlys1 = { - start: { line: bracesLine.line, ch: 9 }, - end: { line: bracesLine.line, ch: 11 } -}; -var seekOutside = { - start: { line: seekBraceLine.line, ch: 1 }, - end: { line: seekBraceLine.line, ch: 16 } -}; -var seekInside = { - start: { line: seekBraceLine.line, ch: 14 }, - end: { line: seekBraceLine.line, ch: 11 } -}; - -function copyCursor(cur) { - return { ch: cur.ch, line: cur.line }; -} - -function forEach(arr, func) { - for (var i = 0; i < arr.length; i++) { - func(arr[i], i, arr); - } -} - -function testVim(name, run, opts, expectedFail) { - var vimOpts = { - lineNumbers: true, - vimMode: true, - showCursorWhenSelecting: true, - value: code - }; - for (var prop in opts) { - if (opts.hasOwnProperty(prop)) { - vimOpts[prop] = opts[prop]; - } - } - return test('vim_' + name, function() { - var place = document.getElementById("testground"); - var cm = CodeMirror(place, vimOpts); - var vim = CodeMirror.Vim.maybeInitVimState_(cm); - - function doKeysFn(cm) { - return function(args) { - if (args instanceof Array) { - arguments = args; - } - for (var i = 0; i < arguments.length; i++) { - CodeMirror.Vim.handleKey(cm, arguments[i]); - } - } - } - function doInsertModeKeysFn(cm) { - return function(args) { - if (args instanceof Array) { arguments = args; } - function executeHandler(handler) { - if (typeof handler == 'string') { - CodeMirror.commands[handler](cm); - } else { - handler(cm); - } - return true; - } - for (var i = 0; i < arguments.length; i++) { - var key = arguments[i]; - // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, 'vim-insert', executeHandler); - // Record for insert mode. - if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { - var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; - if (lastChange) { - lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); - } - } - } - } - } - function doExFn(cm) { - return function(command) { - cm.openDialog = helpers.fakeOpenDialog(command); - helpers.doKeys(':'); - } - } - function assertCursorAtFn(cm) { - return function(line, ch) { - var pos; - if (ch == null && typeof line.line == 'number') { - pos = line; - } else { - pos = makeCursor(line, ch); - } - eqPos(pos, cm.getCursor()); - } - } - function fakeOpenDialog(result) { - return function(text, callback) { - return callback(result); - } - } - function fakeOpenNotification(matcher) { - return function(text) { - matcher(text); - } - } - var helpers = { - doKeys: doKeysFn(cm), - // Warning: Only emulates keymap events, not character insertions. Use - // replaceRange to simulate character insertions. - // Keys are in CodeMirror format, NOT vim format. - doInsertModeKeys: doInsertModeKeysFn(cm), - doEx: doExFn(cm), - assertCursorAt: assertCursorAtFn(cm), - fakeOpenDialog: fakeOpenDialog, - fakeOpenNotification: fakeOpenNotification, - getRegisterController: function() { - return CodeMirror.Vim.getRegisterController(); - } - } - CodeMirror.Vim.resetVimGlobalState_(); - var successful = false; - var savedOpenNotification = cm.openNotification; - try { - run(cm, vim, helpers); - successful = true; - } finally { - cm.openNotification = savedOpenNotification; - // if (!successful || verbose) { - // place.style.visibility = "visible"; - // } else { - // place.removeChild(cm.getWrapperElement()); - // } - } - }, expectedFail); -}; -testVim('qq@q', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); -}, { value: ' '}); -testVim('@@', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); - helpers.doKeys('@', '@'); - helpers.assertCursorAt(0,6); -}, { value: ' '}); -var jumplistScene = ''+ - 'word\n'+ - '(word)\n'+ - '{word\n'+ - 'word.\n'+ - '\n'+ - 'word search\n'+ - '}word\n'+ - 'word\n'+ - 'word\n'; -function testJumplist(name, keys, endPos, startPos, dialog) { - endPos = makeCursor(endPos[0], endPos[1]); - startPos = makeCursor(startPos[0], startPos[1]); - testVim(name, function(cm, vim, helpers) { - CodeMirror.Vim.resetVimGlobalState_(); - if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); - cm.setCursor(startPos); - helpers.doKeys.apply(null, keys); - helpers.assertCursorAt(endPos); - }, {value: jumplistScene}); -}; -testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); -testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); -testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); -testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); -testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); -testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); -testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); -testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); -testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); -testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); -testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); -testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); -testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); -testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); -testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); -testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); -testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); -testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [0,2], [0,2]); -testJumplist('jumplist_skip_delted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [1,0], [0,2]); - -/** - * @param name Name of the test - * @param keys An array of keys or a string with a single key to simulate. - * @param endPos The expected end position of the cursor. - * @param startPos The position the cursor should start at, defaults to 0, 0. - */ -function testMotion(name, keys, endPos, startPos) { - testVim(name, function(cm, vim, helpers) { - if (!startPos) { - startPos = { line: 0, ch: 0 }; - } - cm.setCursor(startPos); - helpers.doKeys(keys); - helpers.assertCursorAt(endPos); - }); -}; - -function makeCursor(line, ch) { - return { line: line, ch: ch }; -}; - -function offsetCursor(cur, offsetLine, offsetCh) { - return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; -}; - -// Motion tests -testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); -testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); -testMotion('h', 'h', makeCursor(0, 0), word1.start); -testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); -testMotion('l', 'l', makeCursor(0, 1)); -testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); -testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); -testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); -testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); -testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); -testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('w', 'w', word1.start); -testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); -testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); -testMotion('w_repeat', ['2', 'w'], word2.start); -testMotion('w_wrap', ['w'], word3.start, word2.start); -testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); -testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); -testMotion('W', 'W', bigWord1.start); -testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); -testMotion('e', 'e', word1.end); -testMotion('e_repeat', ['2', 'e'], word2.end); -testMotion('e_wrap', 'e', word3.end, word2.end); -testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); -testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); -testMotion('b', 'b', word3.start, word3.end); -testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); -testMotion('b_wrap', 'b', word2.start, word3.start); -testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); -testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); -testMotion('ge', ['g', 'e'], word2.end, word3.end); -testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); -testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); -testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), - makeCursor(0, 0)); -testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); -testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), - makeCursor(3, 1)); -testMotion('gg_repeat', ['3', 'g', 'g'], - makeCursor(lines[2].line, lines[2].textStart)); -testMotion('G', 'G', - makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), - makeCursor(3, 1)); -testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, - lines[2].textStart)); -// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. -testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); -testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); -testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); -testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); -testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); -testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); -testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), - makeCursor(0, 3)); -testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); -testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); -testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); -testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), - makeCursor(charLine.line, 0)); -testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), - pChars[0]); -testMotion('F', ['F', 'p'], pChars[0], pChars[1]); -testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); -testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); -testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); -testMotion('%_parens', ['%'], parens1.end, parens1.start); -testMotion('%_squares', ['%'], squares1.end, squares1.start); -testMotion('%_braces', ['%'], curlys1.end, curlys1.start); -testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); -testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); -testVim('%_seek_skip', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,9); -}, {value:'01234"("()'}); -testVim('%_skip_string', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,4); - cm.setCursor(0,2); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(")")'}); -(')') -testVim('%_skip_comment', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,6); - cm.setCursor(0,3); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(/*)*/)'}); -// Make sure that moving down after going to the end of a line always leaves you -// at the end of a line, but preserves the offset in other cases -testVim('Changing lines after Eol operation', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['$']); - helpers.doKeys(['j']); - // After moving to Eol and then down, we should be at Eol of line 2 - helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); - helpers.doKeys(['j']); - // After moving down, we should be at Eol of line 3 - helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); - helpers.doKeys(['h']); - helpers.doKeys(['j']); - // After moving back one space and then down, since line 4 is shorter than line 2, we should - // be at Eol of line 2 - 1 - helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); - helpers.doKeys(['j']); - helpers.doKeys(['j']); - // After moving down again, since line 3 has enough characters, we should be back to the - // same place we were at on line 1 - helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); -}); -//making sure gj and gk recover from clipping -testVim('gj_gk_clipping', function(cm,vim,helpers){ - cm.setCursor(0, 1); - helpers.doKeys('g','j','g','j'); - helpers.assertCursorAt(2, 1); - helpers.doKeys('g','k','g','k'); - helpers.assertCursorAt(0, 1); -},{value: 'line 1\n\nline 2'}); -//testing a mix of j/k and gj/gk -testVim('j_k_and_gj_gk', function(cm,vim,helpers){ - cm.setSize(120); - cm.setCursor(0, 0); - //go to the last character on the first line - helpers.doKeys('$'); - //move up/down on the column within the wrapped line - //side-effect: cursor is not locked to eol anymore - helpers.doKeys('g','k'); - var cur=cm.getCursor(); - eq(cur.line,0); - is((cur.ch<176),'gk didn\'t move cursor back (1)'); - helpers.doKeys('g','j'); - helpers.assertCursorAt(0, 176); - //should move to character 177 on line 2 (j/k preserve character index within line) - helpers.doKeys('j'); - //due to different line wrapping, the cursor can be on a different screen-x now - //gj and gk preserve screen-x on movement, much like moveV - helpers.doKeys('3','g','k'); - cur=cm.getCursor(); - eq(cur.line,1); - is((cur.ch<176),'gk didn\'t move cursor back (2)'); - helpers.doKeys('g','j','2','g','j'); - //should return to the same character-index - helpers.doKeys('k'); - helpers.assertCursorAt(0, 176); -},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); -testVim('gj_gk', function(cm, vim, helpers) { - if (phantom) return; - cm.setSize(120); - // Test top of document edge case. - cm.setCursor(0, 4); - helpers.doKeys('g', 'j'); - helpers.doKeys('10', 'g', 'k'); - helpers.assertCursorAt(0, 4); - - // Test moving down preserves column position. - helpers.doKeys('g', 'j'); - var pos1 = cm.getCursor(); - var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; - helpers.doKeys('g', 'j'); - helpers.assertCursorAt(expectedPos2); - - // Move to the last character - cm.setCursor(0, 0); - // Move left to reset HSPos - helpers.doKeys('h'); - // Test bottom of document edge case. - helpers.doKeys('100', 'g', 'j'); - var endingPos = cm.getCursor(); - is(endingPos != 0, 'gj should not be on wrapped line 0'); - var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); - var endingCharCoords = cm.charCoords(endingPos); - is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); -},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentiallylongtotestmovementofgjandgkoverwrappedlines.' }); -testVim('}', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(1, 0); - cm.setCursor(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(4, 0); - cm.setCursor(0, 0); - helpers.doKeys('6', '}'); - helpers.assertCursorAt(5, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('{', function(cm, vim, helpers) { - cm.setCursor(5, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - cm.setCursor(5, 0); - helpers.doKeys('2', '{'); - helpers.assertCursorAt(1, 0); - cm.setCursor(5, 0); - helpers.doKeys('6', '{'); - helpers.assertCursorAt(0, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('paragraph_motions', function(cm, vim, helpers) { - cm.setCursor(10, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(7, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(16, 0); - - cm.setCursor(9, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(6, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(7, 0); - - // ip inside empty space - cm.setCursor(10, 0); - helpers.doKeys('v', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(12, 0), cm.getCursor('head')); - helpers.doKeys('i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('2', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // should switch to visualLine mode - cm.setCursor(14, 0); - helpers.doKeys('', 'v', 'i', 'p'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(14, 0); - helpers.doKeys('', 'V', 'i', 'p'); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // ap inside empty space - cm.setCursor(10, 0); - helpers.doKeys('', 'v', 'a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(13, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(13, 0), cm.getCursor('anchor')); - eqPos(Pos(14, 0), cm.getCursor('head')); - - cm.setCursor(16, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(14, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(0, 0), cm.getCursor('anchor')); - eqPos(Pos(4, 0), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('d', 'i', 'p'); - var register = helpers.getRegisterController().getRegister(); - eq('a\na\n', register.toString()); - is(register.linewise); - helpers.doKeys('3', 'j', 'p'); - helpers.doKeys('y', 'i', 'p'); - is(register.linewise); - eq('b\na\na\nc\n', register.toString()); -}, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' }); - -// Operator tests -testVim('dl', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'l'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dl_eol', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('d', 'l'); - eq(' word1', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 5); -}, { value: ' word1 ' }); -testVim('dl_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('2', 'd', 'l'); - eq('ord1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' w', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dh', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'h'); - eq(' wrd1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('o', register.toString()); - is(!register.linewise); - eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dj', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dj_end_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dk', function(cm, vim, helpers) { - var curStart = makeCursor(1, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dk_start_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1 ' }); -testVim('dw_space', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dw_word', function(cm, vim, helpers) { - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq(' word2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - 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. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - 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 - // of line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - 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 - // of line and it is followed by multiple newlines. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \n\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\n\nword2' }); -testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq(' \nword', cm.getValue()); -}, { value: '\n \nword' }); -testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('word', cm.getValue()); -}, { value: '\nword' }); -testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \n', cm.getValue()); -}, { value: ' \n \n' }); -testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n\n', cm.getValue()); -}, { value: ' \n\n' }); -testVim('dw_word_whitespace_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \nword2', cm.getValue()); -}, { value: 'word1\n \nword2'}) -testVim('dw_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'w'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('dw_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - cm.setCursor(0, 1); - helpers.doKeys('d', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\nword2' }); -testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('\n\n', cm.getValue()); -}, { value: 'word\n\n' }); -testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('d', 'e'); - eq('wor', cm.getValue()); -}, { value: 'word\n\n\n' }); -testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('', cm.getValue()); -}, { value: ' \n\n\n' }); -testVim('de_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'e'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('db_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\n\n', cm.getValue()); -}, { value: '\n\n\n' }); -testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\nword', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('d', 'b'); - eq('\n\nd', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('db_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'b'); - eq('abc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('dge_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - // Note: In real VIM the result should be '', but it's not quite consistent, - // since 2 newlines are deleted. But in the similar case of word\n\n, only - // 1 newline is deleted. We'll diverge from VIM's behavior since it's much - // easier this way. - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - eq('wor\n', cm.getValue()); -}, { value: 'word\n\n'}); -testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'g', 'e'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('dge_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'g', 'e'); - eq('bc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('d_inclusive', function(cm, vim, helpers) { - // Assert that when inclusive is set, the character the cursor is on gets - // deleted too. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'e'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('d_reverse', function(cm, vim, helpers) { - // Test that deleting in reverse works. - cm.setCursor(1, 0); - helpers.doKeys('d', 'b'); - eq(' word2 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\n', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2 ' }); -testVim('dd', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 1, ch: 0 }); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[1].textStart); -}); -testVim('dd_prefix_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('2', 'd', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_motion_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('d', '2', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 6; - helpers.doKeys('2', 'd', '3', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[6].textStart); -}); -testVim('dd_lastline', function(cm, vim, helpers) { - cm.setCursor(cm.lineCount(), 0); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - helpers.assertCursorAt(cm.lineCount() - 1, 0); -}); -testVim('dd_only_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var expectedRegister = cm.getValue() + "\n"; - helpers.doKeys('d','d'); - eq(1, cm.lineCount()); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedRegister, register.toString()); -}, { value: "thisistheonlyline" }); -// Yank commands should behave the exact same as d commands, expect that nothing -// gets deleted. -testVim('yw_repeat', function(cm, vim, helpers) { - // Assert that yw does yank newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('y', '2', 'w'); - eq(' word1\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('yy_multiply_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount(); - helpers.doKeys('2', 'y', '3', 'y'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eqPos(curStart, cm.getCursor()); -}); -// Change commands behave like d commands except that it also enters insert -// mode. In addition, when the change is linewise, an additional newline is -// inserted so that insert mode starts on that line. -testVim('cw', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('c', '2', 'w'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); -}, { value: 'word1 word2 word3'}); -testVim('cw_repeat', function(cm, vim, helpers) { - // Assert that cw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('c', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2' }); -testVim('cc_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 5; - helpers.doKeys('2', 'c', '3', 'c'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - 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('', 'c', '|'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); - helpers.doKeys('', '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); - helpers.doKeys('c', 'c'); - eq(expectedLineCount, cm.lineCount()); -}); -function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; -} -testVim('c_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); - var replacement = fillArray('hello', 3); - cm.replaceSelections(replacement); - eq('1hello\n5hello\nahellofg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(2, 3); - helpers.doKeys('', '2', 'k', 'h', 'C'); - replacement = fillArray('world', 3); - cm.replaceSelections(replacement); - eq('1hworld\n5hworld\nahworld', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('c_visual_block_replay', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = fillArray('fo', 3); - cm.replaceSelections(replacement); - eq('1fo4\n5fo8\nafodefg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - eq('foo4\nfoo8\nfoodefg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -testVim('d_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'd'); - eq('1\n5\nafg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('D_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'D'); - eq('1\n5\na', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -// Swapcase commands edit in place and do not modify registers. -testVim('g~w_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('g', '~', '2', 'w'); - eq(' WORD1\nWORD2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('g~g~', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedLineCount = cm.lineCount(); - var expectedValue = cm.getValue().toUpperCase(); - helpers.doKeys('2', 'g', '~', '3', 'g', '~'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); -testVim('gu_and_gU', function(cm, vim, helpers) { - var curStart = makeCursor(0, 7); - var value = cm.getValue(); - cm.setCursor(curStart); - helpers.doKeys('2', 'g', 'U', 'w'); - eq(cm.getValue(), 'wa wb xX WC wd'); - eqPos(curStart, cm.getCursor()); - helpers.doKeys('2', 'g', 'u', 'w'); - eq(cm.getValue(), value); - - helpers.doKeys('2', 'g', 'U', 'B'); - eq(cm.getValue(), 'wa WB Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - cm.setCursor(makeCursor(0, 4)); - helpers.doKeys('g', 'u', 'i', 'w'); - eq(cm.getValue(), 'wa wb Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - // TODO: support gUgU guu - // eqPos(makeCursor(0, 0), cm.getCursor()); - - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); -}, { value: 'wa wb xx wc wd' }); -testVim('visual_block_~', function(cm, vim, helpers) { - cm.setCursor(1, 1); - helpers.doKeys('', 'l', 'l', 'j', '~'); - helpers.assertCursorAt(1, 1); - eq('hello\nwoRLd\naBCDe', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', '~'); - helpers.assertCursorAt(2, 0); - eq('hello\nwoRLd\nAbcDe', cm.getValue()); -},{value: 'hello\nwOrld\nabcde' }); -testVim('._swapCase_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'j', 'l', '~'); - cm.setCursor(0, 3); - helpers.doKeys('.'); - eq('HelLO\nWorLd\nAbcdE', cm.getValue()); -},{value: 'hEllo\nwOrlD\naBcDe' }); -testVim('._delete_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'x'); - eq('ive\ne\nsome\nsugar', cm.getValue()); - helpers.doKeys('.'); - eq('ve\n\nsome\nsugar', cm.getValue()); - helpers.doKeys('j', 'j', '.'); - eq('ve\n\nome\nugar', cm.getValue()); - helpers.doKeys('u', '', '.'); - eq('ve\n\nme\ngar', cm.getValue()); -},{value: 'give\nme\nsome\nsugar' }); -testVim('>{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('>', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('>>', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('2', '>', '>'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('<{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('<', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); -testVim('<<', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('2', '<', '<'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); - -// Edit tests -function testEdit(name, before, pos, edit, after) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, edit.split('')); - eq(after, cm.getValue()); - }, {value: before}); -} - -// These Delete tests effectively cover word-wise Change, Visual & Yank. -// Tabs are used as differentiated whitespace to catch edge cases. -// Normal word: -testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); -testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); -testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); -testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); -testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); -testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); -testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); -testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); -testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); -testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); -testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); -testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); -testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); -testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); -// Big word: -testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); -testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); -testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); -testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); -testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); -testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); -// Deleting text objects -// Open and close on same line -testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); -testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); -testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); -testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); -testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); - -testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); -testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); -testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); -testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); - -testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); -testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); -testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); -testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); - -// delete around and inner b. -testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); - -// delete around and inner B. -testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); -testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); - -testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); -testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); -testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); -testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); -testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); -testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); - -// Open and close on different lines, equally indented -testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); -testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); - -// open and close on diff lines, open indented less than close -testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); - -// open and close on diff lines, open indented more than close -testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); -testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); -testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); -testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); - -function testSelection(name, before, pos, keys, sel) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, keys.split('')); - eq(sel, cm.getSelection()); - }, {value: before}); -} -testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); -testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); -testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); -testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); -testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); -testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); -testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); -testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); -testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); - -testVim('mouse_select', function(cm, vim, helpers) { - cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); - is(cm.state.vim.visualMode); - is(!cm.state.vim.visualLine); - is(!cm.state.vim.visualBlock); - helpers.doKeys(''); - is(!cm.somethingSelected()); - helpers.doKeys('g', 'v'); - eq('cd', cm.getSelection()); -}, {value: 'abcdef'}); - -// Operator-motion tests -testVim('D', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('D'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 2); -}, { value: ' word1\nword2\n word3' }); -testVim('C', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('C'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2\n word3' }); -testVim('Y', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('Y'); - eq(' word1\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('~', function(cm, vim, helpers) { - helpers.doKeys('3', '~'); - eq('ABCdefg', cm.getValue()); - helpers.assertCursorAt(0, 3); -}, { value: 'abcdefg' }); - -// Action tests -testVim('ctrl-a', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-9', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-7', cm.getValue()); -}, {value: '-10'}); -testVim('ctrl-x', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-1', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-3', cm.getValue()); -}, {value: '0'}); -testVim('/ search forward', function(cm, vim, helpers) { - forEach(['', ''], function(key) { - cm.setCursor(0, 0); - helpers.doKeys(key); - helpers.assertCursorAt(0, 5); - helpers.doKeys('l'); - helpers.doKeys(key); - helpers.assertCursorAt(0, 10); - cm.setCursor(0, 11); - helpers.doKeys(key); - helpers.assertCursorAt(0, 11); - }); -}, {value: '__jmp1 jmp2 jmp'}); -testVim('a', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 2); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('a_eol', function(cm, vim, helpers) { - cm.setCursor(0, lines[0].length - 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_endOfSelectedArea', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'j', 'l'); - helpers.doKeys('A'); - helpers.assertCursorAt(1, 2); - eq('vim-insert', cm.getOption('keyMap')); -}, {value: 'foo\nbar'}); -testVim('i', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('i'); - helpers.assertCursorAt(0, 1); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('i_repeat', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttest', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: '' }); -testVim('i_repeat_delete', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('2', 'i'); - cm.replaceRange('z', cm.getCursor()); - helpers.doInsertModeKeys('Backspace', 'Backspace'); - helpers.doKeys(''); - eq('abe', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'abcde' }); -testVim('A', function(cm, vim, helpers) { - helpers.doKeys('A'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('testhello\nmehello\npleahellose', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - // TODO this doesn't work yet - // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('I', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('I'); - helpers.assertCursorAt(0, lines[0].textStart); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('I_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'I'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttestblah', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: 'blah' }); -testVim('I_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('hellotest\nhellome\nhelloplease', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('o', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('o'); - eq('word1\n\nword2', cm.getValue()); - helpers.assertCursorAt(1, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('o_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('3', 'o'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('\ntest\ntest\ntest', cm.getValue()); - helpers.assertCursorAt(3, 3); -}, { value: '' }); -testVim('O', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('O'); - eq('\nword1\nword2', cm.getValue()); - helpers.assertCursorAt(0, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('J', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('J'); - var expectedValue = 'word1 word2\nword3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('J_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('3', 'J'); - var expectedValue = 'word1 word2 word3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('p', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('"', 'a', 'p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_wrong_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('p'); - eq('___', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: '___' }); -testVim('p_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_lastline', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\n def', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\ndef', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_with_tab_indents', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true}); -testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); -testVim('[p', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys('[', 'p'); - eq(' abc\n def\n ___', cm.getValue()); -}, { value: ' ___' }); -testVim('P', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('P'); - eq('_abc\ndef__', cm.getValue()); - helpers.assertCursorAt(1, 3); -}, { value: '___' }); -testVim('P_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'P'); - eq(' a\nd\n a\nd\n___', cm.getValue()); - helpers.assertCursorAt(0, 2); -}, { value: '___' }); -testVim('r', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'r', 'u'); - eq('wuuuet\nanother', cm.getValue(),'3r failed'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 4); - helpers.doKeys('v', 'j', 'h', 'r', ''); - eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); -}, { value: 'wordet\nanother' }); -testVim('r_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); - eq('1lll\n5lll\nalllefg', cm.getValue()); - helpers.doKeys('', 'l', 'j', 'r', ''); - eq('1 l\n5 l\nalllefg', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('o'); - helpers.doKeys(''); - cm.replaceRange('\t\t', cm.getCursor()); - helpers.doKeys('', 'h', 'h', 'r', 'r'); - eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('R', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('R'); - helpers.assertCursorAt(0, 1); - eq('vim-replace', cm.getOption('keyMap')); - is(cm.state.overwrite, 'Setting overwrite state failed'); -}); -testVim('mark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(2, 2); - cm.setCursor(2, 0); - cm.replaceRange(' h', cm.getCursor()); - cm.setCursor(0, 0); - helpers.doKeys('\'', 't'); - helpers.assertCursorAt(2, 3); -}); -testVim('jumpToMark_next', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(0, 0); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 4); -}); -testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(4, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(4, 0); -}); -testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 1); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '`'); - helpers.assertCursorAt(0, 0); - var actual = cm.getLine(0); - var expected = 'pop pop 0 1 2 3 4'; - eq(actual, expected, "Deleting while jumping to the next mark failed."); -}); -testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '\''); - helpers.assertCursorAt(0, 1); - var actual = cm.getLine(0); - var expected = ' (a) [b] {c} ' - eq(actual, expected, "Deleting while jumping to the next mark line failed."); -}); -testVim('jumpToMark_prev', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(4, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(4, 0); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { - cm.setCursor(4, 4); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 6); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('delmark_single', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 't'); - helpers.doEx('delmarks t'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(0, 0); -}); -testVim('delmark_range', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b-d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks bcd'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi_space', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b c d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_all', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks a b-de'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(0, 0); -}); -testVim('visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l'); - helpers.assertCursorAt(0, 4); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('d'); - eq('15', cm.getValue()); -}, { value: '12345' }); -testVim('visual_yank', function(cm, vim, helpers) { - helpers.doKeys('v', '3', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('p'); - eq('aa te test for yank', cm.getValue()); -}, { value: 'a test for yank' }) -testVim('visual_w', function(cm, vim, helpers) { - helpers.doKeys('v', 'w'); - eq(cm.getSelection(), 'motion t'); -}, { value: 'motion test'}); -testVim('visual_initial_selection', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v'); - cm.getSelection('n'); -}, { value: 'init'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'l', 'h', 'h'); - cm.getSelection('ro'); -}, { value: 'cross'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'h', 'l', 'l'); - cm.getSelection('os'); -}, { value: 'cross'}); -testVim('visual_crossover_up', function(cm, vim, helpers) { - cm.setCursor(3, 2); - helpers.doKeys('v', 'j', 'k', 'k'); - eqPos(Pos(2, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); - helpers.doKeys('k'); - eqPos(Pos(1, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_crossover_down', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('v', 'k', 'j', 'j'); - eqPos(Pos(2, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); - helpers.doKeys('j'); - eqPos(Pos(3, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_exit', function(cm, vim, helpers) { - helpers.doKeys('', 'l', 'j', 'j', ''); - eqPos(cm.getCursor('anchor'), cm.getCursor('head')); - eq(vim.visualMode, false); -}, { value: 'hello\nworld\nfoo' }); -testVim('visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); - eq(' 4\n 5', cm.getValue()); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_block_move_to_eol', function(cm, vim, helpers) { - // moveToEol should move all block cursors to end of line - cm.setCursor(0, 0); - helpers.doKeys('', 'G', '$'); - var selections = cm.getSelections().join(); - 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 - // i.e. extending the selection - // till the end of the longest line. - helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); - helpers.doKeys('d', 'd', 'd', 'd'); - eq('', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) { - // check for left side selection in case - // of moving up to a shorter line. - cm.replaceRange('', cm.getCursor()); - cm.setCursor(3, 4); - helpers.doKeys('', 'l', 'k', 'k', 'd'); - eq('hello world\n{\ntis\nsa!', cm.getValue()); -}, {value: 'hello world\n{\nthis is\nsparta!'}); -testVim('visual_block_corners', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', '2', 'l', 'k'); - // circle around the anchor - // and check the selections - var selections = cm.getSelections(); - eq('345891', selections.join('')); - helpers.doKeys('4', 'h'); - selections = cm.getSelections(); - eq('123678', selections.join('')); - helpers.doKeys('j', 'j'); - selections = cm.getSelections(); - eq('678abc', selections.join('')); - helpers.doKeys('4', 'l'); - selections = cm.getSelections(); - eq('891cde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_mode_switch', function(cm, vim, helpers) { - // switch between visual modes - cm.setCursor(1, 1); - // blockwise to characterwise visual - helpers.doKeys('', 'j', 'l', 'v'); - selections = cm.getSelections(); - eq('7891\nabc', selections.join('')); - // characterwise to blockwise - helpers.doKeys(''); - selections = cm.getSelections(); - eq('78bc', selections.join('')); - // blockwise to linewise visual - helpers.doKeys('V'); - selections = cm.getSelections(); - eq('67891\nabcde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { - // visual block with long and short lines - cm.setCursor(0, 3); - helpers.doKeys('', 'j', 'j', 'j'); - var selections = cm.getSelections().join(); - eq('4,,d,b', selections); - helpers.doKeys('3', 'k'); - selections = cm.getSelections().join(); - eq('4', selections); - helpers.doKeys('5', 'j', 'k'); - selections = cm.getSelections().join(""); - eq(10, selections.length); -}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); -testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3' , 'l', ''); - eqPos(makeCursor(0, 3), cm.getCursor()); - helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); - eq(cm.getSelections().join(), "3456,,cdef"); - helpers.doKeys('4' , 'h'); - eq(cm.getSelections().join(), "23,8,bc"); - helpers.doKeys('2' , 'l'); - eq(cm.getSelections().join(), "34,,cd"); -}, {value: '123456\n78\nabcdefg\nfoobar'}); - -testVim('visual_marks', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); - // Test visual mode marks - cm.setCursor(2, 1); - helpers.doKeys('\'', '<'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('\'', '>'); - helpers.assertCursorAt(2, 0); -}); -testVim('visual_join', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); - 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); -}, { value: '\n' }); -testVim('reselect_visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); - helpers.assertCursorAt(0, 5); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'l', 'l', 'p'); - eq('123456\n2345\nbar', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('g', 'v'); - // here the fake cursor is at (1, 3) - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', 'g', 'v'); - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); - eqPos(makeCursor(2, 0), cm.getCursor('anchor')); - eq('123456\n2345\nbar', cm.getValue()); -}, { value: '123456\nfoo\nbar' }); -testVim('reselect_visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); - eq('foo\nand\nbar', cm.getValue()); - cm.setCursor(1, 0); - helpers.doKeys('V', 'y', 'j'); - helpers.doKeys('V', 'p' , 'g', 'v', 'd'); - eq('foo\nand', cm.getValue()); -}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); -testVim('reselect_visual_block', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', 'k', 'h', ''); - cm.setCursor(2, 1); - helpers.doKeys('v', 'l', 'g', 'v'); - eqPos(Pos(1, 2), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - // Ensure selection is done with visual block mode rather than one - // continuous range. - eq(cm.getSelections().join(''), '23oo') - helpers.doKeys('g', 'v'); - eqPos(Pos(2, 1), vim.sel.anchor); - eqPos(Pos(2, 2), vim.sel.head); - helpers.doKeys(''); - // Ensure selection of deleted range - cm.setCursor(1, 1); - helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); - eq(cm.getSelections().join(''), 'or'); -}, { value: '123456\nfoo\nbar' }); -testVim('s_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('s'); - helpers.doKeys(''); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('s_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 's'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('o_visual', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys('v','l','l','l','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('v','v','j','j','j','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('O'); - helpers.doKeys('l','l') - helpers.assertCursorAt(3, 3); - helpers.doKeys('d'); - eq('p',cm.getValue()); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('o_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('','3','j','l','l', 'o'); - eqPos(Pos(3, 3), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - helpers.doKeys('O'); - eqPos(Pos(3, 1), vim.sel.anchor); - eqPos(Pos(0, 3), vim.sel.head); - helpers.doKeys('o'); - eqPos(Pos(0, 3), vim.sel.anchor); - eqPos(Pos(3, 1), vim.sel.head); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('changeCase_visual', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('U'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('u'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('l', 'l', 'l', '.'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('j', '@', 'a'); - helpers.assertCursorAt(1, 0); - cm.setCursor(3, 0); - helpers.doKeys('V', 'U', 'j', '.'); - eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); -testVim('changeCase_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 1); - helpers.doKeys('', 'k', 'k', 'h', 'U'); - eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); - cm.setCursor(0, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); - // check when last line is shorter. - cm.setCursor(2, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); -testVim('visual_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p'); - helpers.assertCursorAt(1, 5); - eq('this is a\nunithitest for visual paste', cm.getValue()); - cm.setCursor(0, 0); - // in case of pasting whole line - helpers.doKeys('y', 'y'); - cm.setCursor(1, 6); - helpers.doKeys('v', 'l', 'l', 'l', 'p'); - helpers.assertCursorAt(2, 0); - eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); -}, { value: 'this is a\nunit test for visual paste'}); - -// This checks the contents of the register used to paste the text -testVim('v_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'p'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+register/.test(text)); - }); -}, { value: 'register contents\nare not erased'}); -testVim('S_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(1, 0); - eq('aa\n\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); -testVim('blockwise_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'l', 'y'); - cm.setCursor(0, 2); - // paste one char after the current cursor position - helpers.doKeys('p'); - eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('v', '4', 'l', 'y'); - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'p'); - eq('helheelhelo\norwold\noofo\narba', cm.getValue()); -}, { value: 'hello\nworld\nfoo\nbar'}); -testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { - // extend short lines in case of different line lengths. - cm.setCursor(0, 0); - helpers.doKeys('', 'j', 'j', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('p'); - eq('hellho\nfoo f\nbar b', cm.getValue()); -}, { value: 'hello\nfoo\nbar'}); -testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'x'); - cm.setCursor(0, 0); - helpers.doKeys('P'); - eq('cut\nand\npaste\nme', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); -testVim('blockwise_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', '"', 'a', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('"', 'a', 'p'); - eq('foobfar\nhellho\nworlwd', cm.getValue()); -}, { value: 'foobar\nhello\nworld'}); -testVim('blockwise_paste_last_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'y'); - cm.setCursor(3, 0); - helpers.doKeys('p'); - eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); - -testVim('S_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 'j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - 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('/'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('N'); - helpers.assertCursorAt(0, 11); - - cm.setCursor(0, 0); - helpers.doKeys('2', '/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_case', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('Match'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_2_pcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', true); - cm.openDialog = helpers.fakeOpenDialog('(word){2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_2_nopcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('?_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('? and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('N'); - helpers.assertCursorAt(1, 6); - - cm.setCursor(0, 0); - helpers.doKeys('2', '?'); - helpers.assertCursorAt(0, 11); -}, { value: 'match nope match \n nope Match' }); -testVim('*', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); - - cm.setCursor(0, 9); - helpers.doKeys('2', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_no_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 0); -}, { value: ' \n match \n' }); -testVim('*_symbol', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(1, 0); -}, { value: ' /}\n/} match \n' }); -testVim('#', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); - - cm.setCursor(0, 9); - helpers.doKeys('2', '#'); - helpers.assertCursorAt(0, 22); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_seek', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('#', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('g*', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '*'); - helpers.assertCursorAt(0, 18); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('g#', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '#'); - helpers.assertCursorAt(0, 0); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '#'); - helpers.assertCursorAt(1, 0); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('macro_insert', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '0', 'i'); - cm.replaceRange('foo', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q', '@', 'a'); - eq('foofoo', cm.getValue()); -}, { value: ''}); -testVim('macro_insert_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '$', 'a'); - cm.replaceRange('larry.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('a'); - cm.replaceRange('curly.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('a'); - cm.replaceRange('moe.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('@', 'a'); - // At this point, the most recent edit should be the 2nd insert change - // inside the macro, i.e. "curly.". - helpers.doKeys('.'); - eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); -}, { value: ''}); -testVim('macro_space', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', ''); - helpers.assertCursorAt(0, 2); - helpers.doKeys('q', 'a', '', '', 'q'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 8); -}, { value: 'one line of text.'}); -testVim('macro_t_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 't', 'e', 'q'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('l', '@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('l', ';'); - helpers.assertCursorAt(0, 12); -}, { value: 'one line of text.'}); -testVim('macro_f_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'b', 'f', 'e', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'b'); - helpers.assertCursorAt(0, 7); - helpers.doKeys(';'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_slash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'c'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'c'); - helpers.assertCursorAt(0, 7); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_multislash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'd'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('t'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 12); - helpers.doKeys('@', 'd'); - helpers.assertCursorAt(0, 15); -}, { value: 'one line of text to rule them all.'}); -testVim('macro_parens', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', 'i'); - cm.replaceRange('(', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('e', 'a'); - cm.replaceRange(')', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('w', '@', 'z'); - helpers.doKeys('w', '@', 'z'); - eq('(see) (spot) (run)', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_overwrite', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', '0', 'i'); - cm.replaceRange('I ', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e'); - // Now replace the macro with something else. - helpers.doKeys('q', 'z', 'a'); - cm.replaceRange('.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e', '@', 'z'); - helpers.doKeys('e', '@', 'z'); - eq('I see. spot. run.', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_search_f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'f', ' '); - helpers.assertCursorAt(0,3); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,3); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('macro_search_2f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '2', 'f', ' '); - helpers.assertCursorAt(0,9); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,9); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('yank_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'b', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo/.test(text)); - is(/b\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+oo\nar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foobar/.test(text)); - is(/"\s+foobar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('macro_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'i'); - cm.replaceRange('gangnam', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('q', 'b', 'o'); - cm.replaceRange('style', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+i/.test(text)); - is(/b\s+o/.test(text)); - }); - helpers.doKeys(':'); -}, { value: ''}); -testVim('._register', function(cm,vim,helpers) { - cm.setCursor(0,0); - helpers.doKeys('i'); - cm.replaceRange('foo',cm.getCursor()); - helpers.doKeys(''); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\.\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim(':_register', function(cm,vim,helpers) { - helpers.doEx('bar'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/:\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register_escape', function(cm, vim, helpers) { - // Check that the register is restored if the user escapes rather than confirms. - cm.openDialog = helpers.fakeOpenDialog('waldo'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var KEYCODES = { - f: 70, - o: 79, - Esc: 27 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - onKeyUp = options.onKeyUp; - }; - var close = function() {}; - helpers.doKeys('/'); - // Fake some keyboard events coming in. - onKeyDown({keyCode: KEYCODES.f}, '', close); - onKeyUp({keyCode: KEYCODES.f}, '', close); - onKeyDown({keyCode: KEYCODES.o}, 'f', close); - onKeyUp({keyCode: KEYCODES.o}, 'f', close); - onKeyDown({keyCode: KEYCODES.o}, 'fo', close); - onKeyUp({keyCode: KEYCODES.o}, 'fo', close); - onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/waldo/.test(text)); - is(!/foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('foo'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\/\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('this'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('search'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('history'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var query = ''; - var keyCodes = { - Up: 38, - Down: 40 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') query = newVal; - } - helpers.doKeys('/'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'checks'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'history'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'search'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'this'); - onKeyDown({keyCode: keyCodes.Down}, query, close); - onKeyUp({keyCode: keyCodes.Down}, query, close); - eq(query, 'search'); -}, {value: ''}); -testVim('exCommand_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('registers'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('sort'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('map'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('invalid'); - helpers.doKeys(':'); - var onKeyDown; - var onKeyUp; - var input = ''; - var keyCodes = { - Up: 38, - Down: 40, - s: 115 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys(':'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'invalid'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'map'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'registers'); - onKeyDown({keyCode: keyCodes.s}, '', close); - input = 's'; - 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'); - helpers.doKeys('.'); - eq('5 6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('3', '.'); - eq('6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._insert', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('testestt', cm.getValue()); - helpers.assertCursorAt(0, 6); -}, { value: ''}); -testVim('._insert_repeat', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - cm.setCursor(0, 4); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('testesttestt', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._repeat_insert', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('te', cm.getCursor()); - cm.setCursor(0, 2); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('tetettetetee', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._insert_o', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - cm.setCursor(1, 1); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('\nz\nz', cm.getValue()); - helpers.assertCursorAt(2, 0); -}, { value: ''}); -testVim('._insert_o_repeat', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 0); - helpers.doKeys('2', '.'); - eq('\nz\nz\nz', cm.getValue()); - helpers.assertCursorAt(3, 0); -}, { value: ''}); -testVim('._insert_o_indent', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 2); - helpers.doKeys('.'); - eq('{\n z\n z', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '{'}); -testVim('._insert_cw', function(cm, vim, helpers) { - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 3); - helpers.doKeys('2', 'l'); - helpers.doKeys('.'); - eq('test test word3', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._insert_cw_repeat', function(cm, vim, helpers) { - // For some reason, repeat cw in desktop VIM will does not repeat insert mode - // changes. Will conform to that behavior. - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 4); - helpers.doKeys('l'); - helpers.doKeys('2', '.'); - eq('test test', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._delete', function(cm, vim, helpers) { - cm.setCursor(0, 5); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('zace', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zabcde'}); -testVim('._delete_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('zzce', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zzabcde'}); -testVim('._visual_>', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('V', 'j', '>'); - cm.setCursor(2, 0) - helpers.doKeys('.'); - eq(' 1\n 2\n 3\n 4', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '1\n2\n3\n4'}); -testVim('f;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F;', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('F', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx6x8x'}); -testVim('t;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '0xx3xx678x'}); -testVim('f,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('f', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F,', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('F', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('t,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('t', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(3, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T,', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('T', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx67xx'}); -testVim('fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('td,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Td,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('012340123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'P'); - eq('012345678456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('012345678945678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('012340123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('01230123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'p'); - eq('01234567895678', cm.getValue()); -}, { value: '0123456789'}); -testVim('Ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('01234567895678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('01230123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('HML', function(cm, vim, helpers) { - var lines = 35; - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(120, 0); - cm.refresh(); //ace! - helpers.doKeys('H'); - helpers.assertCursorAt(86, 2); - helpers.doKeys('L'); - helpers.assertCursorAt(120, 4); - helpers.doKeys('M'); - helpers.assertCursorAt(103,4); -}, { value: (function(){ - var lines = new Array(100); - var upper = ' xx\n'; - var lower = ' xx\n'; - upper = lines.join(upper); - lower = lines.join(lower); - return upper + lower; -})()}); - -var zVals = []; -forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ - var lineNum = 250; - var lines = 35; - testVim(e, function(cm, vim, helpers) { - var k1 = e[0]; - var k2 = e.substring(1); - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(lineNum, 0); - helpers.doKeys(k1, k2); - zVals[idx] = cm.getScrollInfo().top; - }, { value: (function(){ - return new Array(500).join('\n'); - })()}); -}); -testVim('zb', function(cm, vim, helpers){ - eq(zVals[2], zVals[5]); -}); - -var moveTillCharacterSandbox = - 'The quick brown fox \n' - 'jumped over the lazy dog.' -testVim('moveTillCharacter', function(cm, vim, helpers){ - cm.setCursor(0, 0); - // Search for the 'q'. - cm.openDialog = helpers.fakeOpenDialog('q'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); - // Jump to just before the first o in the list. - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick brown fox \n', cm.getValue()); - // Delete that one character. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick bown fox \n', cm.getValue()); - // Delete everything until the next 'o'. - helpers.doKeys('.'); - eq('The quick box \n', cm.getValue()); - // An unmatched character should have no effect. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('q'); - eq('The quick box \n', cm.getValue()); - // Matches should only be possible on single lines. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('z'); - eq('The quick box \n', cm.getValue()); - // After all that, the search for 'q' should still be active, so the 'N' command - // can run it again in reverse. Use that to delete everything back to the 'q'. - helpers.doKeys('d'); - helpers.doKeys('N'); - eq('The ox \n', cm.getValue()); - eq(4, cm.getCursor().ch); -}, { value: moveTillCharacterSandbox}); -testVim('searchForPipe', function(cm, vim, helpers){ - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(0, 0); - // Search for the '|'. - cm.openDialog = helpers.fakeOpenDialog('|'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); -}, { value: 'this|that'}); - - -var scrollMotionSandbox = - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n' - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; -testVim('scrollMotion', function(cm, vim, helpers){ - var prevCursor, prevScrollInfo; - cm.setCursor(0, 0); - // ctrl-y at the top of the file should have no effect. - helpers.doKeys(''); - eq(0, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(1, cm.getCursor().line); - is(prevScrollInfo.top < cm.getScrollInfo().top); - // Jump to the end of the sandbox. - cm.setCursor(1000, 0); - cm.refresh(); //ace! - prevCursor = cm.getCursor(); - // ctrl-e at the bottom of the file should have no effect. - helpers.doKeys(''); - eq(prevCursor.line, cm.getCursor().line); - cm.refresh(); //ace! - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(prevCursor.line - 1, cm.getCursor().line, "Y"); - is(prevScrollInfo.top > cm.getScrollInfo().top); -}, { value: scrollMotionSandbox}); - -var squareBracketMotionSandbox = ''+ - '({\n'+//0 - ' ({\n'+//11 - ' /*comment {\n'+//2 - ' */(\n'+//3 - '#else \n'+//4 - ' /* )\n'+//5 - '#if }\n'+//6 - ' )}*/\n'+//7 - ')}\n'+//8 - '{}\n'+//9 - '#else {{\n'+//10 - '{}\n'+//11 - '}\n'+//12 - '{\n'+//13 - '#endif\n'+//14 - '}\n'+//15 - '}\n'+//16 - '#else';//17 -testVim('[[, ]]', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(9,0); - helpers.doKeys('2', ']', ']'); - helpers.assertCursorAt(13,0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(13,0); - helpers.doKeys('2', '[', '['); - helpers.assertCursorAt(9,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[], ][', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(12,0); - helpers.doKeys('2', ']', '['); - helpers.assertCursorAt(16,0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(16,0); - helpers.doKeys('2', '[', ']'); - helpers.assertCursorAt(12,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[{, ]}', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(2,12); - helpers.doKeys('2', '[', '{'); - helpers.assertCursorAt(0,1); - cm.setCursor(4, 10); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(6,11); - helpers.doKeys('2', ']', '}'); - helpers.assertCursorAt(8,1); - cm.setCursor(0,1); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(8,1); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(0,1); -}, { value: squareBracketMotionSandbox}); -testVim('[(, ])', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '('); - helpers.assertCursorAt(3,14); - helpers.doKeys('2', '[', '('); - helpers.assertCursorAt(0,0); - cm.setCursor(4, 10); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(5,11); - helpers.doKeys('2', ']', ')'); - helpers.assertCursorAt(8,0); - helpers.doKeys('[', '('); - helpers.assertCursorAt(0,0); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(8,0); -}, { value: squareBracketMotionSandbox}); -testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { - forEach(['*', '/'], function(key){ - cm.setCursor(7, 0); - helpers.doKeys('2', '[', key); - helpers.assertCursorAt(2,2); - helpers.doKeys('2', ']', key); - helpers.assertCursorAt(7,5); - }); -}, { value: squareBracketMotionSandbox}); -testVim('[#, ]#', function(cm, vim, helpers) { - cm.setCursor(10, 3); - helpers.doKeys('2', '[', '#'); - helpers.assertCursorAt(4,0); - helpers.doKeys('5', ']', '#'); - helpers.assertCursorAt(17,0); - cm.setCursor(10, 3); - helpers.doKeys(']', '#'); - helpers.assertCursorAt(14,0); -}, { value: squareBracketMotionSandbox}); -testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { - cm.setCursor(11, 0); - helpers.doKeys('[', 'm'); - helpers.assertCursorAt(10,7); - helpers.doKeys('4', '[', 'm'); - helpers.assertCursorAt(1,3); - helpers.doKeys('5', ']', 'm'); - helpers.assertCursorAt(11,0); - helpers.doKeys('[', 'M'); - helpers.assertCursorAt(9,1); - helpers.doKeys('3', ']', 'M'); - helpers.assertCursorAt(15,0); - helpers.doKeys('5', '[', 'M'); - helpers.assertCursorAt(7,3); -}, { value: squareBracketMotionSandbox}); - -// Ex mode tests -testVim('ex_go_to_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('4'); - helpers.assertCursorAt(3, 0); -}, { value: 'a\nb\nc\nd\ne\n'}); -testVim('ex_write', function(cm, vim, helpers) { - var tmp = CodeMirror.commands.save; - var written; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Test that w, wr, wri ... write all trigger :write. - var command = 'write'; - for (var i = 1; i < command.length; i++) { - written = false; - actualCm = null; - helpers.doEx(command.substring(0, i)); - eq(written, true); - eq(actualCm, cm); - } - CodeMirror.commands.save = tmp; -}); -testVim('ex_sort', function(cm, vim, helpers) { - helpers.doEx('sort'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_reverse', function(cm, vim, helpers) { - helpers.doEx('sort!'); - eq('d\nc\nb\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_range', function(cm, vim, helpers) { - helpers.doEx('2,3sort'); - eq('b\nc\nd\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_oneline', function(cm, vim, helpers) { - helpers.doEx('2sort'); - // Expect no change. - eq('b\nd\nc\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { - helpers.doEx('sort i'); - eq('a\nb\nc\nd\nZ', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_unique', function(cm, vim, helpers) { - helpers.doEx('sort u'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\na\na\nd\na\nc\na'}); -testVim('ex_sort_decimal', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('d3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\nz-9'}); -testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('.9\n6\n s5\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_hex', function(cm, vim, helpers) { - helpers.doEx('sort x'); - eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n&0xB\n.9'}); -testVim('ex_sort_octal', function(cm, vim, helpers) { - helpers.doEx('sort o'); - eq('.8\n.9\nd3\n s5\n6', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\n.8'}); -testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('y\nz\nc1\nb2\na3', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('a3\nb2\nc1\nz\ny', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -// test for :global command -testVim('ex_global', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('g/one/s//two'); - eq('two two\n two two\n two two', cm.getValue()); - helpers.doEx('1,2g/two/s//one'); - eq('one one\n one one\n two two', cm.getValue()); -}, {value: 'one one\n one one\n one one'}); -testVim('ex_global_confirm', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var onKeyDown; - var openDialogSave = cm.openDialog; - var KEYCODES = { - a: 65, - n: 78, - q: 81, - y: 89 - }; - // Intercept the ex command, 'global' - cm.openDialog = function(template, callback, options) { - // Intercept the prompt for the embedded ex command, 'substitute' - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - callback('g/one/s//two/gc'); - }; - helpers.doKeys(':'); - var close = function() {}; - onKeyDown({keyCode: KEYCODES.n}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - onKeyDown({keyCode: KEYCODES.a}, '', close); - onKeyDown({keyCode: KEYCODES.q}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); -}, {value: 'one one\n one one\n one one\n one one\n one one'}); -// Basic substitute tests. -testVim('ex_substitute_same_line', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('s/one/two/g'); - eq('one one\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_full_file', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('%s/one/two/g'); - eq('two two\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_input_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('1,3s/\\d/0/g'); - eq('0\n0\n0\n4', cm.getValue()); -}, { value: '1\n2\n3\n4' }); -testVim('ex_substitute_visual_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - // Set last visual mode selection marks '< and '> at lines 2 and 4 - helpers.doKeys('V', '2', 'j', 'v'); - helpers.doEx('\'<,\'>s/\\d/0/g'); - eq('1\n0\n0\n0\n5', cm.getValue()); -}, { value: '1\n2\n3\n4\n5' }); -testVim('ex_substitute_empty_query', function(cm, vim, helpers) { - // If the query is empty, use last query. - cm.setCursor(1, 0); - cm.openDialog = helpers.fakeOpenDialog('1'); - helpers.doKeys('/'); - helpers.doEx('s//b/g'); - eq('abb ab2 ab3', cm.getValue()); -}, { value: 'a11 a12 a13' }); -testVim('ex_substitute_javascript', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(1, 0); - // Throw all the things that javascript likes to treat as special values - // into the replace part. All should be literal (this is VIM). - helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') - eq('a $$ $\' $` $& 0 b', cm.getValue()); -}, { value: 'a 0 b' }); -testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { - cm.setCursor(0, 0); - helpers.doEx('s/a/b/g'); - cm.setCursor(1, 0); - helpers.doEx('s'); - eq('b b\nb a', cm.getValue()); -}, {value: 'a a\na a'}); - -// More complex substitute tests that test both pcre and nopcre options. -function testSubstitute(name, options) { - testVim(name + '_pcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', true); - helpers.doEx(options.expr); - eq(options.expectedValue, cm.getValue()); - }, options); - // If no noPcreExpr is defined, assume that it's the same as the expr. - var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; - testVim(name + '_nopcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', false); - helpers.doEx(noPcreExpr); - eq(options.expectedValue, cm.getValue()); - }, options); -} -testSubstitute('ex_substitute_capture', { - value: 'a11 a12 a13', - expectedValue: 'a1111 a1212 a1313', - // $n is a backreference - expr: 's/(\\d+)/$1$1/g', - // \n is a backreference. - noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); -testSubstitute('ex_substitute_capture2', { - value: 'a 0 b', - expectedValue: 'a $00 b', - expr: 's/(\\d+)/$$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a11 a12 a13', - expectedValue: 'a$1$1 a$1$1 a$1$1', - expr: 's/(\\d+)/$$1$$1/g', - noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); -testSubstitute('ex_substitute_nocapture2', { - value: 'a 0 b', - expectedValue: 'a $10 b', - expr: 's/(\\d+)/$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a b c', - expectedValue: 'a $ c', - expr: 's/b/$$/', - noPcreExpr: 's/b/$/'}); -testSubstitute('ex_substitute_slash_regex', { - value: 'one/two \n three/four', - expectedValue: 'one|two \n three|four', - expr: '%s/\\//|'}); -testSubstitute('ex_substitute_pipe_regex', { - value: 'one|two \n three|four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\|/,/', - noPcreExpr: '%s/|/,/'}); -testSubstitute('ex_substitute_or_regex', { - value: 'one|two \n three|four', - expectedValue: 'ana|twa \n thraa|faar', - expr: '%s/o|e|u/a/g', - noPcreExpr: '%s/o\\|e\\|u/a/g'}); -testSubstitute('ex_substitute_or_word_regex', { - value: 'one|two \n three|four', - expectedValue: 'five|five \n three|four', - expr: '%s/(one|two)/five/g', - noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); -testSubstitute('ex_substitute_backslashslash_regex', { - value: 'one\\two \n three\\four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\\\/,'}); -testSubstitute('ex_substitute_slash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one/two \n three/four', - expr: '%s/,/\\/'}); -testSubstitute('ex_substitute_backslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\two \n three\\four', - expr: '%s/,/\\\\/g'}); -testSubstitute('ex_substitute_multibackslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. - expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. -testSubstitute('ex_substitute_braces_word', { - value: 'ababab abb ab{2}', - expectedValue: 'ab abb ab{2}', - expr: '%s/(ab){2}//g', - noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_range', { - value: 'a aa aaa aaaa', - expectedValue: 'a a', - expr: '%s/a{2,3}//g', - noPcreExpr: '%s/a\\{2,3\\}//g'}); -testSubstitute('ex_substitute_braces_literal', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab abb ', - expr: '%s/ab\\{2\\}//g', - noPcreExpr: '%s/ab{2}//g'}); -testSubstitute('ex_substitute_braces_char', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_no_escape', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2}//g'}); -testSubstitute('ex_substitute_count', { - value: '1\n2\n3\n4', - expectedValue: '1\n0\n0\n4', - expr: 's/\\d/0/i 2'}); -testSubstitute('ex_substitute_count_with_range', { - value: '1\n2\n3\n4', - expectedValue: '1\n2\n0\n0', - expr: '1,3s/\\d/0/ 3'}); -testSubstitute('ex_substitute_not_global', { - value: 'aaa\nbaa\ncaa', - expectedValue: 'xaa\nbxa\ncxa', - expr: '%s/a/x/'}); -function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { - testVim(name, function(cm, vim, helpers) { - var savedOpenDialog = cm.openDialog; - var savedKeyName = CodeMirror.keyName; - var onKeyDown; - var recordedCallback; - var closed = true; // Start out closed, set false on second openDialog. - function close() { - closed = true; - } - // First openDialog should save callback. - cm.openDialog = function(template, callback, options) { - recordedCallback = callback; - } - // Do first openDialog. - helpers.doKeys(':'); - // Second openDialog should save keyDown handler. - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - closed = false; - }; - // Return the command to Vim and trigger second openDialog. - recordedCallback(command); - // The event should really use keyCode, but here just mock it out and use - // key and replace keyName to just return key. - CodeMirror.keyName = function (e) { return e.key; } - keys = keys.toUpperCase(); - for (var i = 0; i < keys.length; i++) { - is(!closed); - onKeyDown({ key: keys.charAt(i) }, '', close); - } - try { - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(finalPos); - is(closed); - } catch(e) { - throw e - } finally { - // Restore overriden functions. - CodeMirror.keyName = savedKeyName; - cm.openDialog = savedOpenDialog; - } - }, { value: initialValue }); -}; -testSubstituteConfirm('ex_substitute_confirm_emptydoc', - '%s/x/b/c', '', '', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_nomatch', - '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_accept', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_random_keys', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_some', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_accept_then_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_quit', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_last', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_oneline', - '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_range_accept', - '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_some', - '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_all', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_last', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); -//:noh should clear highlighting of search-results but allow to resume search through n -testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.doEx('noh'); - eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); -}, { value: 'match nope match \n nope Match' }); -testVim('set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - CodeMirror.Vim.setOption('testoption', '5'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', false); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - helpers.doEx('set testoption=22'); - fail(); - } catch (expected) {}; - // Test setOption - helpers.doEx('set notestoption'); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set non-string. - CodeMirror.Vim.setOption('testoption', true); - fail(); - } catch (expected) {}; - try { - // Test fail to set 'notestoption' - CodeMirror.Vim.setOption('notestoption', 'b'); - fail(); - } catch (expected) {}; - // Test setOption - CodeMirror.Vim.setOption('testoption', 'c'); - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testopt', 'a', 'string'); - // 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 - 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) { - helpers.doEx('map a x'); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_unmap_key2key', function(cm, vim, helpers) { - helpers.doEx('unmap a'); - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { - try { - helpers.doEx('unmap a'); - fail(); - } catch (expected) {} - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { - helpers.doEx('map ; :'); - var dialogOpened = false; - cm.openDialog = function() { - dialogOpened = true; - } - helpers.doKeys(';'); - eq(dialogOpened, true); -}); -testVim('ex_map_ex2key:', function(cm, vim, helpers) { - helpers.doEx('map :del x'); - helpers.doEx('del'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_map_ex2ex', function(cm, vim, helpers) { - helpers.doEx('map :del :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doEx('del'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2ex', function(cm, vim, helpers) { - helpers.doEx('map a :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doKeys('a'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { - CodeMirror.Vim.map('b', ':w', 'visual'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Mapping should not work in normal mode. - helpers.doKeys('b'); - eq(written, false); - // Mapping should work in visual mode. - helpers.doKeys('v', 'b'); - eq(written, true); - eq(actualCm, cm); - - CodeMirror.commands.save = tmp; -}); -testVim('ex_imap', function(cm, vim, helpers) { - CodeMirror.Vim.map('jk', '', 'insert'); - helpers.doKeys('i'); - is(vim.insertMode); - helpers.doKeys('j', 'k'); - is(!vim.insertMode); -}) - -// Testing registration of functions as ex-commands and mapping to -keys -testVim('ex_api_test', function(cm, vim, helpers) { - var res=false; - var val='from'; - CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ - if(params.args)val=params.args[0]; - else res=true; - }); - helpers.doEx(':ext to'); - eq(val,'to','Defining ex-command failed'); - CodeMirror.Vim.map('',':ext'); - helpers.doKeys('',''); - is(res,'Mapping to key failed'); -}); -// For now, this test needs to be last because it messes up : for future tests. -testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { - helpers.doEx('map : x'); - helpers.doKeys(':'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); - -// Test event handlers -testVim('beforeSelectionChange', function(cm, vim, helpers) { - cm.setCursor(0, 100); - eqPos(cm.getCursor('head'), cm.getCursor('anchor')); -}, { value: 'abc' }); - - -}); - - -if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec(); -} diff --git a/lib/ace/layer/cursor.js b/lib/ace/layer/cursor.js index 53c30e56..26ade52b 100644 --- a/lib/ace/layer/cursor.js +++ b/lib/ace/layer/cursor.js @@ -32,15 +32,11 @@ define(function(require, exports, module) { "use strict"; var dom = require("../lib/dom"); -var IE8; var Cursor = function(parentEl) { this.element = dom.createElement("div"); this.element.className = "ace_layer ace_cursor-layer"; parentEl.appendChild(this.element); - - if (IE8 === undefined) - IE8 = "opacity" in this.element; this.isVisible = false; this.isBlinking = true; @@ -50,22 +46,9 @@ var Cursor = function(parentEl) { this.cursors = []; this.cursor = this.addCursor(); dom.addCssClass(this.element, "ace_hidden-cursors"); - this.$updateCursors = this.$updateVisibility.bind(this); }; (function() { - - this.$updateVisibility = function(val) { - var cursors = this.cursors; - for (var i = cursors.length; i--; ) - cursors[i].style.visibility = val ? "" : "hidden"; - }; - this.$updateOpacity = function(val) { - var cursors = this.cursors; - for (var i = cursors.length; i--; ) - cursors[i].style.opacity = val ? "" : "0"; - }; - this.$padding = 0; this.setPadding = function(padding) { @@ -91,13 +74,12 @@ var Cursor = function(parentEl) { }; this.setSmoothBlinking = function(smoothBlinking) { - if (smoothBlinking != this.smoothBlinking && !IE8) { + if (smoothBlinking != this.smoothBlinking) { this.smoothBlinking = smoothBlinking; - dom.setCssClass(this.element, "ace_smooth-blinking", smoothBlinking); - this.$updateCursors(true); - this.$updateCursors = (smoothBlinking - ? this.$updateOpacity - : this.$updateVisibility).bind(this); + if (smoothBlinking) + dom.addCssClass(this.element, "ace_smooth-blinking"); + else + dom.removeCssClass(this.element, "ace_smooth-blinking"); this.restartTimer(); } }; @@ -131,34 +113,35 @@ var Cursor = function(parentEl) { }; this.restartTimer = function() { - var update = this.$updateCursors; clearInterval(this.intervalId); clearTimeout(this.timeoutId); - if (this.smoothBlinking) { + if (this.smoothBlinking) dom.removeCssClass(this.element, "ace_smooth-blinking"); - } - - update(true); + for (var i = this.cursors.length; i--; ) + this.cursors[i].style.opacity = ""; if (!this.isBlinking || !this.blinkInterval || !this.isVisible) return; - if (this.smoothBlinking) { + if (this.smoothBlinking) setTimeout(function(){ dom.addCssClass(this.element, "ace_smooth-blinking"); }.bind(this)); - } - + var blink = function(){ this.timeoutId = setTimeout(function() { - update(false); - }, 0.6 * this.blinkInterval); + for (var i = this.cursors.length; i--; ) { + this.cursors[i].style.opacity = 0; + } + }.bind(this), 0.6 * this.blinkInterval); }.bind(this); this.intervalId = setInterval(function() { - update(true); + for (var i = this.cursors.length; i--; ) { + this.cursors[i].style.opacity = ""; + } blink(); - }, this.blinkInterval); + }.bind(this), this.blinkInterval); blink(); }; @@ -190,20 +173,16 @@ var Cursor = function(parentEl) { for (var i = 0, n = selections.length; i < n; i++) { var pixelPos = this.getPixelPosition(selections[i].cursor, true); if ((pixelPos.top > config.height + config.offset || - pixelPos.top < 0) && i > 1) { + pixelPos.top < -config.offset) && i > 1) { continue; } var style = (this.cursors[cursorIndex++] || this.addCursor()).style; - - if (!this.drawCursor) { - style.left = pixelPos.left + "px"; - style.top = pixelPos.top + "px"; - style.width = config.characterWidth + "px"; - style.height = config.lineHeight + "px"; - } else { - this.drawCursor(style, pixelPos, config, selections[i], this.session); - } + + style.left = pixelPos.left + "px"; + style.top = pixelPos.top + "px"; + style.width = config.characterWidth + "px"; + style.height = config.lineHeight + "px"; } while (this.cursors.length > cursorIndex) this.removeCursor(); @@ -215,8 +194,6 @@ var Cursor = function(parentEl) { this.$pixelPos = pixelPos; this.restartTimer(); }; - - this.drawCursor = null; this.$setOverwrite = function(overwrite) { if (overwrite != this.overwrite) { diff --git a/lib/ace/layer/font_metrics.js b/lib/ace/layer/font_metrics.js deleted file mode 100644 index 715c6cf3..00000000 --- a/lib/ace/layer/font_metrics.js +++ /dev/null @@ -1,176 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define(function(require, exports, module) { - -var oop = require("../lib/oop"); -var dom = require("../lib/dom"); -var lang = require("../lib/lang"); -var useragent = require("../lib/useragent"); -var EventEmitter = require("../lib/event_emitter").EventEmitter; - -var CHAR_COUNT = 0; - -var FontMetrics = exports.FontMetrics = function(parentEl, interval) { - this.el = dom.createElement("div"); - this.$setMeasureNodeStyles(this.el.style, true); - - this.$main = dom.createElement("div"); - this.$setMeasureNodeStyles(this.$main.style); - - this.$measureNode = dom.createElement("div"); - this.$setMeasureNodeStyles(this.$measureNode.style); - - - this.el.appendChild(this.$main); - this.el.appendChild(this.$measureNode); - parentEl.appendChild(this.el); - - if (!CHAR_COUNT) - this.$testFractionalRect(); - this.$measureNode.innerHTML = lang.stringRepeat("X", CHAR_COUNT); - - this.$characterSize = {width: 0, height: 0}; - this.checkForSizeChanges(); -}; - -(function() { - - oop.implement(this, EventEmitter); - - this.$characterSize = {width: 0, height: 0}; - - this.$testFractionalRect = function() { - var el = dom.createElement("div"); - this.$setMeasureNodeStyles(el.style); - el.style.width = "0.2px"; - document.documentElement.appendChild(el); - var w = el.getBoundingClientRect().width; - if (w > 0 && w < 1) - CHAR_COUNT = 50; - else - CHAR_COUNT = 100; - el.parentNode.removeChild(el); - }; - - this.$setMeasureNodeStyles = function(style, isRoot) { - style.width = style.height = "auto"; - style.left = style.top = "0px"; - style.visibility = "hidden"; - style.position = "absolute"; - style.whiteSpace = "pre"; - - if (useragent.isIE < 8) { - style["font-family"] = "inherit"; - } else { - style.font = "inherit"; - } - style.overflow = isRoot ? "hidden" : "visible"; - }; - - this.checkForSizeChanges = function() { - var size = this.$measureSizes(); - if (size && (this.$characterSize.width !== size.width || this.$characterSize.height !== size.height)) { - this.$measureNode.style.fontWeight = "bold"; - var boldSize = this.$measureSizes(); - this.$measureNode.style.fontWeight = ""; - this.$characterSize = size; - this.charSizes = Object.create(null); - this.allowBoldFonts = boldSize && boldSize.width === size.width && boldSize.height === size.height; - this._emit("changeCharacterSize", {data: size}); - } - }; - - this.$pollSizeChanges = function() { - if (this.$pollSizeChangesTimer) - return this.$pollSizeChangesTimer; - var self = this; - return this.$pollSizeChangesTimer = setInterval(function() { - self.checkForSizeChanges(); - }, 500); - }; - - this.setPolling = function(val) { - if (val) { - this.$pollSizeChanges(); - } else if (this.$pollSizeChangesTimer) { - clearInterval(this.$pollSizeChangesTimer); - this.$pollSizeChangesTimer = 0; - } - }; - - this.$measureSizes = function() { - if (CHAR_COUNT === 50) { - var rect = null; - try { - rect = this.$measureNode.getBoundingClientRect(); - } catch(e) { - rect = {width: 0, height:0 }; - }; - var size = { - height: rect.height, - width: rect.width / CHAR_COUNT - }; - } else { - var size = { - height: this.$measureNode.clientHeight, - width: this.$measureNode.clientWidth / CHAR_COUNT - }; - } - // Size and width can be null if the editor is not visible or - // detached from the document - if (size.width === 0 || size.height === 0) - return null; - return size; - }; - - this.$measureCharWidth = function(ch) { - this.$main.innerHTML = lang.stringRepeat(ch, CHAR_COUNT); - var rect = this.$main.getBoundingClientRect(); - return rect.width / CHAR_COUNT; - }; - - this.getCharacterWidth = function(ch) { - var w = this.charSizes[ch]; - if (w === undefined) { - this.charSizes[ch] = this.$measureCharWidth(ch) / this.$characterSize.width; - } - return w; - }; - - this.destroy = function() { - clearInterval(this.$pollSizeChangesTimer); - if (this.el && this.el.parentNode) - this.el.parentNode.removeChild(this.el); - }; - -}).call(FontMetrics.prototype); - -}); diff --git a/lib/ace/layer/gutter.js b/lib/ace/layer/gutter.js index dc1055c2..40dc71a1 100644 --- a/lib/ace/layer/gutter.js +++ b/lib/ace/layer/gutter.js @@ -58,8 +58,7 @@ var Gutter = function(parentEl) { if (this.session) this.session.removeEventListener("change", this.$updateAnnotations); this.session = session; - if (session) - session.on("change", this.$updateAnnotations); + session.on("change", this.$updateAnnotations); }; this.addGutterDecoration = function(row, className){ @@ -76,7 +75,8 @@ var Gutter = function(parentEl) { this.setAnnotations = function(annotations) { // iterate over sparse array - this.$annotations = []; + this.$annotations = [] + var rowInfo, row; for (var i = 0; i < annotations.length; i++) { var annotation = annotations[i]; var row = annotation.row; @@ -100,36 +100,34 @@ var Gutter = function(parentEl) { } }; - this.$updateAnnotations = function (delta) { + this.$updateAnnotations = function (e) { if (!this.$annotations.length) return; - var firstRow = delta.start.row; - var len = delta.end.row - firstRow; + var delta = e.data; + var range = delta.range; + var firstRow = range.start.row; + var len = range.end.row - firstRow; if (len === 0) { // do nothing - } else if (delta.action == 'remove') { + } else if (delta.action == "removeText" || delta.action == "removeLines") { this.$annotations.splice(firstRow, len + 1, null); } else { - var args = new Array(len + 1); + var args = Array(len + 1); args.unshift(firstRow, 1); this.$annotations.splice.apply(this.$annotations, args); } }; this.update = function(config) { - var session = this.session; var firstRow = config.firstRow; - var lastRow = Math.min(config.lastRow + config.gutterOffset, // needed to compensate for hor scollbar - session.getLength() - 1); - var fold = session.getNextFoldLine(firstRow); + var lastRow = config.lastRow; + var fold = this.session.getNextFoldLine(firstRow); var foldStart = fold ? fold.start.row : Infinity; - var foldWidgets = this.$showFoldWidgets && session.foldWidgets; - var breakpoints = session.$breakpoints; - var decorations = session.$decorations; - var firstLineNumber = session.$firstLineNumber; + var foldWidgets = this.$showFoldWidgets && this.session.foldWidgets; + var breakpoints = this.session.$breakpoints; + var decorations = this.session.$decorations; + var firstLineNumber = this.session.$firstLineNumber; var lastLineNumber = 0; - - var gutterRenderer = session.gutterRenderer || this.$renderer; var cell = null; var index = -1; @@ -137,7 +135,7 @@ var Gutter = function(parentEl) { while (true) { if (row > foldStart) { row = fold.end.row + 1; - fold = session.getNextFoldLine(row, fold); + fold = this.session.getNextFoldLine(row, fold); foldStart = fold ? fold.start.row : Infinity; } if (row > lastRow) { @@ -158,7 +156,7 @@ var Gutter = function(parentEl) { this.$cells[index] = cell; } - var className = "ace_gutter-cell "; + var className = "ace_gutter-cell"; if (breakpoints[row]) className += breakpoints[row]; if (decorations[row]) @@ -168,15 +166,19 @@ var Gutter = function(parentEl) { if (cell.element.className != className) cell.element.className = className; - var height = session.getRowLength(row) * config.lineHeight + "px"; + var height = this.session.getRowLength(row) * config.lineHeight + "px"; if (height != cell.element.style.height) cell.element.style.height = height; + var text = lastLineNumber = row + firstLineNumber; + if (text != cell.textNode.data) + cell.textNode.data = text; + if (foldWidgets) { var c = foldWidgets[row]; // check if cached value is invalidated and we need to recompute if (c == null) - c = foldWidgets[row] = session.getFoldWidget(row); + c = foldWidgets[row] = this.session.getFoldWidget(row); } if (c) { @@ -196,30 +198,21 @@ var Gutter = function(parentEl) { if (cell.foldWidget.style.height != height) cell.foldWidget.style.height = height; } else { - if (cell.foldWidget) { + if (cell.foldWidget != null) { cell.element.removeChild(cell.foldWidget); cell.foldWidget = null; } } - - var text = lastLineNumber = gutterRenderer - ? gutterRenderer.getText(session, row) - : row + firstLineNumber; - if (text != cell.textNode.data) - cell.textNode.data = text; row++; } this.element.style.height = config.minHeight + "px"; - if (this.$fixedWidth || session.$useWrapMode) - lastLineNumber = session.getLength() + firstLineNumber; + if (this.$fixedWidth || this.session.$useWrapMode) + lastLineNumber = this.session.getLength(); - var gutterWidth = gutterRenderer - ? gutterRenderer.getWidth(session, lastLineNumber, config) - : lastLineNumber.toString().length * config.characterWidth; - + var gutterWidth = lastLineNumber.toString().length * config.characterWidth; var padding = this.$padding || this.$computePadding(); gutterWidth += padding.left + padding.right; if (gutterWidth !== this.gutterWidth && !isNaN(gutterWidth)) { @@ -231,19 +224,6 @@ var Gutter = function(parentEl) { this.$fixedWidth = false; - this.$showLineNumbers = true; - this.$renderer = ""; - this.setShowLineNumbers = function(show) { - this.$renderer = !show && { - getWidth: function() {return ""}, - getText: function() {return ""} - }; - }; - - this.getShowLineNumbers = function() { - return this.$showLineNumbers; - }; - this.$showFoldWidgets = true; this.setShowFoldWidgets = function(show) { if (show) diff --git a/lib/ace/layer/marker.js b/lib/ace/layer/marker.js index 9818d225..cd1b992d 100644 --- a/lib/ace/layer/marker.js +++ b/lib/ace/layer/marker.js @@ -90,40 +90,37 @@ var Marker = function(parentEl) { else this.drawMultiLineMarker(html, range, marker.clazz, config); } else { - this.drawSingleLineMarker(html, range, marker.clazz + " ace_start" + " ace_br15", config); + this.drawSingleLineMarker(html, range, marker.clazz + " ace_start", config); } } - this.element.innerHTML = html.join(""); + this.element = dom.setInnerHtml(this.element, html.join("")); }; this.$getTop = function(row, layerConfig) { 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) { - 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); + // 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); } }; @@ -137,7 +134,7 @@ var Marker = function(parentEl) { extraStyle = extraStyle || ""; stringBuilder.push( - "
    " - + lang.stringRepeat(this.TAB_CHAR, i) + tabStr.push("" + + this.TAB_CHAR + + lang.stringRepeat("\xa0", i - 1) + ""); } else { - tabStr.push(lang.stringRepeat(" ", i)); + tabStr.push(lang.stringRepeat("\xa0", i)); } } if (this.displayIndentGuides) { this.$indentGuideRe = /\s\S| \t|\t |\s$/; var className = "ace_indent-guide"; - var spaceClass = ""; - var tabClass = ""; if (this.showInvisibles) { className += " ace_invisible"; - spaceClass = " ace_invisible_space"; - tabClass = " ace_invisible_tab"; var spaceContent = lang.stringRepeat(this.SPACE_CHAR, this.tabSize); - var tabContent = lang.stringRepeat(this.TAB_CHAR, this.tabSize); + var tabContent = this.TAB_CHAR + lang.stringRepeat("\xa0", this.tabSize - 1); } else{ - var spaceContent = lang.stringRepeat(" ", this.tabSize); + var spaceContent = lang.stringRepeat("\xa0", this.tabSize); var tabContent = spaceContent; } - this.$tabStrings[" "] = "" + spaceContent + ""; - this.$tabStrings["\t"] = "" + tabContent + ""; + this.$tabStrings[" "] = "" + spaceContent + ""; + this.$tabStrings["\t"] = "" + tabContent + ""; } }; @@ -202,8 +294,7 @@ var Text = function(parentEl) { this.$renderLine( html, row, !this.$useLineGroups(), row == foldStart ? foldLine : false ); - lineElement.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; - lineElement.innerHTML = html.join(""); + dom.setInnerHtml(lineElement, html.join("")); } row++; } @@ -269,11 +360,10 @@ var Text = function(parentEl) { if (this.$useLineGroups()) { container.className = 'ace_line_group'; fragment.appendChild(container); - container.style.height = config.lineHeight * this.session.getRowLength(row) + "px"; - } else { - while(container.firstChild) - fragment.appendChild(container.firstChild); + var lines = container.childNodes + while(lines.length) + fragment.appendChild(lines[0]); } row++; @@ -301,7 +391,7 @@ var Text = function(parentEl) { break; if (this.$useLineGroups()) - html.push("
    ") + html.push("
    ") this.$renderLine(html, row, false, row == foldStart ? foldLine : false); @@ -310,7 +400,7 @@ var Text = function(parentEl) { row++; } - this.element.innerHTML = html.join(""); + this.element = dom.setInnerHtml(this.element, html.join("")); }; this.$textToken = { @@ -321,12 +411,12 @@ var Text = function(parentEl) { this.$renderToken = function(stringBuilder, screenColumn, token, value) { var self = this; - 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 replaceReg = /\t|&|<|( +)|([\x00-\x1f\x80-\xa0\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 - ? "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" - : c; + return self.showInvisibles ? + "" + lang.stringRepeat(self.SPACE_CHAR, c.length) + "" : + lang.stringRepeat("\xa0", c.length); } else if (c == "&") { return "&"; } else if (c == "<") { @@ -337,14 +427,14 @@ var Text = function(parentEl) { return self.$tabStrings[tabSize]; } else if (c == "\u3000") { // U+3000 is both invisible AND full-width, so must be handled uniquely - var classToUse = self.showInvisibles ? "ace_cjk ace_invisible ace_invisible_space" : "ace_cjk"; + var classToUse = self.showInvisibles ? "ace_cjk ace_invisible" : "ace_cjk"; var space = self.showInvisibles ? self.SPACE_CHAR : ""; screenColumn += 1; return "" + space + ""; } else if (b) { - return "" + self.SPACE_CHAR + ""; + return "" + self.SPACE_CHAR + ""; } else { screenColumn += 1; return "" + "
    " ); } @@ -483,7 +568,7 @@ var Text = function(parentEl) { row = foldLine.end.row stringBuilder.push( - "", + "", row == this.session.getLength() - 1 ? this.EOF_CHAR : this.EOL_CHAR, "" ); diff --git a/lib/ace/layer/text_test.js b/lib/ace/layer/text_test.js index 3946ec66..a14a37e6 100644 --- a/lib/ace/layer/text_test.js +++ b/lib/ace/layer/text_test.js @@ -81,17 +81,17 @@ module.exports = { this.textLayer.$renderLine(stringBuilder, 0, true); assert.equal( stringBuilder.join(""), - "" + this.textLayer.SPACE_CHAR + "" - + "\xB6" + "" + this.textLayer.SPACE_CHAR + "" + + "\xB6" ); }, - - "test rendering of indent guides" : function() { + + "test rendering of indent guides" : function() { var textLayer = this.textLayer - var EOL = "" + textLayer.EOL_CHAR + ""; - var SPACE = function(i) {return Array(i+1).join(" ")} + var EOL = "" + textLayer.EOL_CHAR + ""; + var SPACE = function(i) {return Array(i+1).join("\xa0")} var DOT = function(i) {return Array(i+1).join(textLayer.SPACE_CHAR)} - var TAB = function(i) {return Array(i+1).join(textLayer.TAB_CHAR)} + var TAB = function(i) {return textLayer.TAB_CHAR + SPACE(i-1)} function testRender(results) { for (var i = results.length; i--; ) { var stringBuilder = []; @@ -108,13 +108,13 @@ module.exports = { ]); this.textLayer.setShowInvisibles(true); testRender([ - "" + DOT(4) + "" + DOT(2) + "" + EOL, - "" + TAB(4) + "" + TAB(4) + "f" + EOL, + "" + DOT(4) + "" + DOT(2) + "" + EOL, + "" + TAB(4) + "" + TAB(4) + "f" + EOL, ]); this.textLayer.setDisplayIndentGuides(false); testRender([ - "" + DOT(6) + "" + EOL, - "" + TAB(4) + "" + TAB(4) + "f" + EOL + "" + DOT(6) + "" + EOL, + "" + TAB(4) + "" + TAB(4) + "f" + EOL ]); } }; diff --git a/lib/ace/lib/app_config.js b/lib/ace/lib/app_config.js deleted file mode 100644 index 4fe78a1d..00000000 --- a/lib/ace/lib/app_config.js +++ /dev/null @@ -1,157 +0,0 @@ -/* ***** 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) { -"no use strict"; - -var oop = require("./oop"); -var EventEmitter = require("./event_emitter").EventEmitter; - -var optionsProvider = { - setOptions: function(optList) { - Object.keys(optList).forEach(function(key) { - this.setOption(key, optList[key]); - }, this); - }, - getOptions: function(optionNames) { - var result = {}; - if (!optionNames) { - optionNames = Object.keys(this.$options); - } else if (!Array.isArray(optionNames)) { - result = optionNames; - optionNames = Object.keys(result); - } - optionNames.forEach(function(key) { - result[key] = this.getOption(key); - }, this); - return result; - }, - setOption: function(name, value) { - if (this["$" + name] === value) - return; - var opt = this.$options[name]; - if (!opt) { - return warn('misspelled option "' + name + '"'); - } - if (opt.forwardTo) - return this[opt.forwardTo] && this[opt.forwardTo].setOption(name, value); - - if (!opt.handlesSet) - this["$" + name] = value; - if (opt && opt.set) - opt.set.call(this, value); - }, - getOption: function(name) { - var opt = this.$options[name]; - if (!opt) { - return warn('misspelled option "' + name + '"'); - } - if (opt.forwardTo) - return this[opt.forwardTo] && this[opt.forwardTo].getOption(name); - return opt && opt.get ? opt.get.call(this) : this["$" + name]; - } -}; - -function warn(message) { - if (typeof console != "undefined" && console.warn) - console.warn.apply(console, arguments); -} - -function reportError(msg, data) { - var e = new Error(msg); - e.data = data; - if (typeof console == "object" && console.error) - console.error(e); - setTimeout(function() { throw e; }); -} - -var AppConfig = function() { - this.$defaultOptions = {}; -}; - -(function() { - // module loading - oop.implement(this, EventEmitter); - /* - * option {name, value, initialValue, setterName, set, get } - */ - this.defineOptions = function(obj, path, options) { - if (!obj.$options) - this.$defaultOptions[path] = obj.$options = {}; - - Object.keys(options).forEach(function(key) { - var opt = options[key]; - if (typeof opt == "string") - opt = {forwardTo: opt}; - - opt.name || (opt.name = key); - obj.$options[opt.name] = opt; - if ("initialValue" in opt) - obj["$" + opt.name] = opt.initialValue; - }); - - // implement option provider interface - oop.implement(obj, optionsProvider); - - return this; - }; - - this.resetOptions = function(obj) { - Object.keys(obj.$options).forEach(function(key) { - var opt = obj.$options[key]; - if ("value" in opt) - obj.setOption(key, opt.value); - }); - }; - - this.setDefaultValue = function(path, name, value) { - var opts = this.$defaultOptions[path] || (this.$defaultOptions[path] = {}); - if (opts[name]) { - if (opts.forwardTo) - this.setDefaultValue(opts.forwardTo, name, value); - else - opts[name].value = value; - } - }; - - this.setDefaultValues = function(path, optionHash) { - Object.keys(optionHash).forEach(function(key) { - this.setDefaultValue(path, key, optionHash[key]); - }, this); - }; - - this.warn = warn; - this.reportError = reportError; - -}).call(AppConfig.prototype); - -exports.AppConfig = AppConfig; - -}); diff --git a/lib/ace/lib/dom.js b/lib/ace/lib/dom.js index 2cbfe23e..b3724009 100644 --- a/lib/ace/lib/dom.js +++ b/lib/ace/lib/dom.js @@ -31,6 +31,9 @@ define(function(require, exports, module) { "use strict"; +if (typeof document == "undefined") + return; + var XHTML_NS = "http://www.w3.org/1999/xhtml"; exports.getDocumentHead = function(doc) { @@ -46,7 +49,7 @@ exports.createElement = function(tag, ns) { }; exports.hasCssClass = function(el, name) { - var classes = (el.className || "").split(/\s+/g); + var classes = el.className.split(/\s+/g); return classes.indexOf(name) !== -1; }; @@ -91,11 +94,6 @@ 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 include @@ -177,7 +175,6 @@ exports.getInnerHeight = function(element) { ); }; - if (window.pageYOffset !== undefined) { exports.getPageScrollTop = function() { return window.pageYOffset; diff --git a/lib/ace/lib/event.js b/lib/ace/lib/event.js index 57924056..691d0019 100644 --- a/lib/ace/lib/event.js +++ b/lib/ace/lib/event.js @@ -33,6 +33,7 @@ define(function(require, exports, module) { var keys = require("./keys"); var useragent = require("./useragent"); +var dom = require("./dom"); exports.addListener = function(elem, type, callback) { if (elem.addEventListener) { @@ -85,7 +86,7 @@ exports.preventDefault = function(e) { exports.getButton = function(e) { if (e.type == "dblclick") return 0; - if (e.type == "contextmenu" || (useragent.isMac && (e.ctrlKey && !e.altKey && !e.shiftKey))) + if (e.type == "contextmenu" || (e.ctrlKey && useragent.isMac)) return 2; // DOM Event @@ -111,14 +112,12 @@ exports.capture = function(el, eventHandler, releaseCaptureHandler) { exports.addListener(document, "mousemove", eventHandler, true); exports.addListener(document, "mouseup", onMouseUp, true); exports.addListener(document, "dragstart", onMouseUp, true); - - return onMouseUp; }; exports.addMouseWheelListener = function(el, callback) { if ("onmousewheel" in el) { + var factor = 8; exports.addListener(el, "mousewheel", function(e) { - var factor = 8; if (e.wheelDeltaX !== undefined) { e.wheelX = -e.wheelDeltaX / factor; e.wheelY = -e.wheelDeltaY / factor; @@ -130,19 +129,8 @@ exports.addMouseWheelListener = function(el, callback) { }); } else if ("onwheel" in el) { exports.addListener(el, "wheel", function(e) { - var factor = 0.35; - switch (e.deltaMode) { - case e.DOM_DELTA_PIXEL: - e.wheelX = e.deltaX * factor || 0; - e.wheelY = e.deltaY * factor || 0; - break; - case e.DOM_DELTA_LINE: - case e.DOM_DELTA_PAGE: - e.wheelX = (e.deltaX || 0) * 5; - e.wheelY = (e.deltaY || 0) * 5; - break; - } - + e.wheelX = (e.deltaX || 0) * 5; + e.wheelY = (e.deltaY || 0) * 5; callback(e); }); } else { @@ -161,7 +149,7 @@ exports.addMouseWheelListener = function(el, callback) { exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbackName) { var clicks = 0; - var startX, startY, timer; + var startX, startY, timer; var eventNames = { 2: "dblclick", 3: "tripleclick", @@ -169,7 +157,7 @@ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbac }; exports.addListener(el, "mousedown", function(e) { - if (exports.getButton(e) !== 0) { + if (exports.getButton(e) != 0) { clicks = 0; } else if (e.detail > 1) { clicks++; @@ -180,19 +168,14 @@ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbac } if (useragent.isIE) { var isNewClick = Math.abs(e.clientX - startX) > 5 || Math.abs(e.clientY - startY) > 5; - if (!timer || isNewClick) + if (isNewClick) { clicks = 1; - if (timer) - clearTimeout(timer); - timer = setTimeout(function() {timer = null}, timeouts[clicks - 1] || 600); - + } if (clicks == 1) { startX = e.clientX; startY = e.clientY; } } - - e._clicks = clicks; eventHandler[callbackName]("mousedown", e); @@ -214,67 +197,69 @@ exports.addMultiMouseDownListener = function(el, timeouts, eventHandler, callbac } }; -var getModifierHash = useragent.isMac && useragent.isOpera && !("KeyboardEvent" in window) - ? function(e) { - return 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); - } - : function(e) { - return 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); - }; - -exports.getModifierString = function(e) { - return keys.KEY_MODS[getModifierHash(e)]; -}; - function normalizeCommandKeys(callback, e, keyCode) { - var hashId = getModifierHash(e); + var hashId = 0; + if ((useragent.isOpera && !("KeyboardEvent" in window)) && useragent.isMac) { + hashId = 0 | (e.metaKey ? 1 : 0) | (e.altKey ? 2 : 0) + | (e.shiftKey ? 4 : 0) | (e.ctrlKey ? 8 : 0); + } else { + hashId = 0 | (e.ctrlKey ? 1 : 0) | (e.altKey ? 2 : 0) + | (e.shiftKey ? 4 : 0) | (e.metaKey ? 8 : 0); + } if (!useragent.isMac && pressedKeys) { if (pressedKeys[91] || pressedKeys[92]) hashId |= 8; if (pressedKeys.altGr) { if ((3 & hashId) != 3) - pressedKeys.altGr = 0; + pressedKeys.altGr = 0 else return; } if (keyCode === 18 || keyCode === 17) { - var location = "location" in e ? e.location : e.keyLocation; + var location = e.location || e.keyLocation; if (keyCode === 17 && location === 1) { - if (pressedKeys[keyCode] == 1) - ts = e.timeStamp; + ts = e.timeStamp; } else if (keyCode === 18 && hashId === 3 && location === 2) { - var dt = e.timeStamp - ts; - if (dt < 50) + var dt = -ts; + ts = e.timeStamp; + dt += ts; + if (dt < 3) pressedKeys.altGr = true; } } } if (keyCode in keys.MODIFIER_KEYS) { - keyCode = -1; + switch (keys.MODIFIER_KEYS[keyCode]) { + case "Alt": + hashId = 2; + break; + case "Shift": + hashId = 4; + break; + case "Ctrl": + hashId = 1; + break; + default: + hashId = 8; + break; + } + keyCode = 0; } if (hashId & 8 && (keyCode === 91 || keyCode === 93)) { - keyCode = -1; + keyCode = 0; } if (!hashId && keyCode === 13) { - var location = "location" in e ? e.location : e.keyLocation; - if (location === 3) { - callback(e, hashId, -keyCode); + if (e.location || e.keyLocation === 3) { + callback(e, hashId, -keyCode) if (e.defaultPrevented) return; } } - if (useragent.isChromeOS && hashId & 8) { - callback(e, hashId, keyCode); - if (e.defaultPrevented) - return; - else - hashId &= ~8; - } // If there is no hashId and the keyCode is not a function key, then // we don't call the callback as we don't handle a command key here @@ -283,6 +268,8 @@ function normalizeCommandKeys(callback, e, keyCode) { return false; } + + return callback(e, hashId, keyCode); } @@ -308,7 +295,7 @@ exports.addCommandKeyListener = function(el, callback) { var lastDefaultPrevented = null; addListener(el, "keydown", function(e) { - pressedKeys[e.keyCode] = (pressedKeys[e.keyCode] || 0) + 1; + pressedKeys[e.keyCode] = true; var result = normalizeCommandKeys(callback, e, e.keyCode); lastDefaultPrevented = e.defaultPrevented; return result; @@ -326,14 +313,13 @@ exports.addCommandKeyListener = function(el, callback) { }); if (!pressedKeys) { - resetPressedKeys(); - addListener(window, "focus", resetPressedKeys); + pressedKeys = Object.create(null); + addListener(window, "focus", function(e) { + pressedKeys = Object.create(null); + }); } } }; -function resetPressedKeys(e) { - pressedKeys = Object.create(null); -} if (window.postMessage && !useragent.isOldIE) { var postMessageId = 1; diff --git a/lib/ace/lib/keys.js b/lib/ace/lib/keys.js index 465d4a8d..42d427b1 100644 --- a/lib/ace/lib/keys.js +++ b/lib/ace/lib/keys.js @@ -34,8 +34,6 @@ For more information about SproutCore, visit http://www.sproutcore.com define(function(require, exports, module) { "use strict"; -require("./fixoldbrowsers"); - var oop = require("./oop"); /* @@ -48,8 +46,8 @@ var Keys = (function() { }, KEY_MODS: { - "ctrl": 1, "alt": 2, "option" : 2, "shift": 4, - "super": 8, "meta": 8, "command": 8, "cmd": 8 + "ctrl": 1, "alt": 2, "option" : 2, + "shift": 4, "meta": 8, "command": 8, "cmd": 8 }, FUNCTION_KEYS : { @@ -104,21 +102,14 @@ 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: '.', - 186: ';', 187: '=', 188: ',', 189: '-', 190: '.', 191: '/', 192: '`', - 219: '[', 220: '\\',221: ']', 222: '\'' + 188: ',', 190: '.', 191: '/', 192: '`', 219: '[', 220: '\\', + 221: ']', 222: '\'' } }; // A reverse map of FUNCTION_KEYS - var name, i; - for (i in ret.FUNCTION_KEYS) { - name = ret.FUNCTION_KEYS[i].toLowerCase(); - ret[name] = parseInt(i, 10); - } - - // A reverse map of PRINTABLE_KEYS - for (i in ret.PRINTABLE_KEYS) { - name = ret.PRINTABLE_KEYS[i].toLowerCase(); + for (var i in ret.FUNCTION_KEYS) { + var name = ret.FUNCTION_KEYS[i].toLowerCase(); ret[name] = parseInt(i, 10); } @@ -132,32 +123,16 @@ var Keys = (function() { ret.enter = ret["return"]; ret.escape = ret.esc; ret.del = ret["delete"]; - + // workaround for firefox bug ret[173] = '-'; - - (function() { - var mods = ["cmd", "ctrl", "alt", "shift"]; - for (var i = Math.pow(2, mods.length); i--;) { - ret.KEY_MODS[i] = mods.filter(function(x) { - return i & ret.KEY_MODS[x]; - }).join("-") + "-"; - } - })(); - - ret.KEY_MODS[0] = ""; - ret.KEY_MODS[-1] = "input-"; return ret; })(); oop.mixin(exports, Keys); exports.keyCodeToString = function(keyCode) { - // Language-switching keystroke in Chrome/Linux emits keyCode 0. - var keyString = Keys[keyCode]; - if (typeof keyString != "string") - keyString = String.fromCharCode(keyCode); - return keyString.toLowerCase(); -}; + return (Keys[keyCode] || String.fromCharCode(keyCode)).toLowerCase(); +} }); diff --git a/lib/ace/lib/lang.js b/lib/ace/lib/lang.js index 921dee1d..4e6ebf2c 100644 --- a/lib/ace/lib/lang.js +++ b/lib/ace/lib/lang.js @@ -31,10 +31,6 @@ define(function(require, exports, module) { "use strict"; -exports.last = function(a) { - return a[a.length - 1]; -}; - exports.stringReverse = function(string) { return string.split("").reverse().join(""); }; @@ -81,24 +77,18 @@ exports.copyArray = function(array){ return copy; }; -exports.deepCopy = function deepCopy(obj) { - if (typeof obj !== "object" || !obj) +exports.deepCopy = function (obj) { + if (typeof obj != "object") { 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; - copy = cons(); + var copy = obj.constructor(); for (var key in obj) { - copy[key] = deepCopy(obj[key]); + if (typeof obj[key] == "object") { + copy[key] = this.deepCopy(obj[key]); + } else { + copy[key] = obj[key]; + } } return copy; }; @@ -154,6 +144,7 @@ exports.getMatchOffsets = function(string, regExp) { /* deprecated */ exports.deferredCall = function(fcn) { + var timer = null; var callback = function() { timer = null; @@ -179,10 +170,6 @@ exports.deferredCall = function(fcn) { timer = null; return deferred; }; - - deferred.isPending = function() { - return timer; - }; return deferred; }; @@ -196,15 +183,15 @@ exports.delayedCall = function(fcn, defaultTimeout) { }; var _self = function(timeout) { - if (timer == null) - timer = setTimeout(callback, timeout || defaultTimeout); - }; - - _self.delay = function(timeout) { timer && clearTimeout(timer); timer = setTimeout(callback, timeout || defaultTimeout); }; - _self.schedule = _self; + + _self.delay = _self; + _self.schedule = function(timeout) { + if (timer == null) + timer = setTimeout(callback, timeout || 0); + }; _self.call = function() { this.cancel(); diff --git a/lib/ace/lib/net.js b/lib/ace/lib/net.js index bba76df8..3869da45 100644 --- a/lib/ace/lib/net.js +++ b/lib/ace/lib/net.js @@ -38,14 +38,4 @@ exports.loadScript = function(path, callback) { }; }; -/* - * Convert a url into a fully qualified absolute URL - * This function does not work in IE6 - */ -exports.qualifyURL = function(url) { - var a = document.createElement('a'); - a.href = url; - return a.href; -} - }); diff --git a/lib/ace/lib/oop.js b/lib/ace/lib/oop.js index 85725f0f..f3dbb1d9 100644 --- a/lib/ace/lib/oop.js +++ b/lib/ace/lib/oop.js @@ -31,17 +31,15 @@ define(function(require, exports, module) { "use strict"; -exports.inherits = function(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); -}; +exports.inherits = (function() { + var tempCtor = function() {}; + return function(ctor, superCtor) { + tempCtor.prototype = superCtor.prototype; + ctor.super_ = superCtor.prototype; + ctor.prototype = new tempCtor(); + ctor.prototype.constructor = ctor; + }; +}()); exports.mixin = function(obj, mixin) { for (var key in mixin) { diff --git a/lib/ace/lib/useragent.js b/lib/ace/lib/useragent.js index 0d1d9f4d..b6989a8c 100644 --- a/lib/ace/lib/useragent.js +++ b/lib/ace/lib/useragent.js @@ -76,16 +76,15 @@ exports.isLinux = (os == "linux"); // Windows Store JavaScript apps (aka Metro apps written in HTML5 and JavaScript) do not use the "Microsoft Internet Explorer" string in their user agent, but "MSAppHost" instead. exports.isIE = (navigator.appName == "Microsoft Internet Explorer" || navigator.appName.indexOf("MSAppHost") >= 0) - ? parseFloat((ua.match(/(?:MSIE |Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]) - : parseFloat((ua.match(/(?:Trident\/[0-9]+[\.0-9]+;.*rv:)([0-9]+[\.0-9]+)/)||[])[1]); // for ie + && parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]); exports.isOldIE = exports.isIE && exports.isIE < 9; // Is this Firefox or related? -exports.isGecko = exports.isMozilla = (window.Controllers || window.controllers) && window.navigator.product === "Gecko"; +exports.isGecko = exports.isMozilla = window.controllers && window.navigator.product === "Gecko"; // oldGecko == rev < 2.0 -exports.isOldGecko = exports.isGecko && parseInt((ua.match(/rv\:(\d+)/)||[])[1], 10) < 4; +exports.isOldGecko = exports.isGecko && parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1], 10) < 4; // Is this Opera exports.isOpera = window.opera && Object.prototype.toString.call(window.opera) == "[object Opera]"; @@ -101,6 +100,4 @@ exports.isIPad = ua.indexOf("iPad") >= 0; exports.isTouchPad = ua.indexOf("TouchPad") >= 0; -exports.isChromeOS = ua.indexOf(" CrOS ") >= 0; - }); diff --git a/lib/ace/line_widgets.js b/lib/ace/line_widgets.js deleted file mode 100644 index ba87d857..00000000 --- a/lib/ace/line_widgets.js +++ /dev/null @@ -1,295 +0,0 @@ -/* ***** 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 dom = require("./lib/dom"); -var Range = require("./range").Range; - - -function LineWidgets(session) { - this.session = session; - this.session.widgetManager = this; - this.session.getRowLength = this.getRowLength; - this.session.$getWidgetScreenLength = this.$getWidgetScreenLength; - this.updateOnChange = this.updateOnChange.bind(this); - this.renderWidgets = this.renderWidgets.bind(this); - this.measureWidgets = this.measureWidgets.bind(this); - this.session._changedWidgets = []; - this.$onChangeEditor = this.$onChangeEditor.bind(this); - - this.session.on("change", this.updateOnChange); - this.session.on("changeEditor", this.$onChangeEditor); -} - -(function() { - this.getRowLength = function(row) { - var h; - if (this.lineWidgets) - h = this.lineWidgets[row] && this.lineWidgets[row].rowCount || 0; - else - h = 0; - if (!this.$useWrapMode || !this.$wrapData[row]) { - return 1 + h; - } else { - return this.$wrapData[row].length + 1 + h; - } - }; - - this.$getWidgetScreenLength = function() { - var screenRows = 0; - this.lineWidgets.forEach(function(w){ - if (w && w.rowCount) - screenRows +=w.rowCount; - }); - return screenRows; - }; - - this.$onChangeEditor = function(e) { - this.attach(e.editor); - }; - - this.attach = function(editor) { - if (editor && editor.widgetManager && editor.widgetManager != this) - editor.widgetManager.detach(); - - if (this.editor == editor) - return; - - this.detach(); - this.editor = editor; - - if (editor) { - editor.widgetManager = this; - editor.renderer.on("beforeRender", this.measureWidgets); - editor.renderer.on("afterRender", this.renderWidgets); - } - }; - this.detach = function(e) { - var editor = this.editor; - if (!editor) - return; - - this.editor = null; - editor.widgetManager = null; - - editor.renderer.off("beforeRender", this.measureWidgets); - editor.renderer.off("afterRender", this.renderWidgets); - var lineWidgets = this.session.lineWidgets; - lineWidgets && lineWidgets.forEach(function(w) { - if (w && w.el && w.el.parentNode) { - w._inDocument = false; - w.el.parentNode.removeChild(w.el); - } - }); - }; - - this.updateOnChange = function(delta) { - var lineWidgets = this.session.lineWidgets; - if (!lineWidgets) return; - - var startRow = delta.start.row; - var len = delta.end.row - startRow; - - if (len === 0) { - // return - } else if (delta.action == 'remove') { - var removed = lineWidgets.splice(startRow + 1, len); - removed.forEach(function(w) { - w && this.removeLineWidget(w); - }, this); - this.$updateRows(); - } else { - var args = new Array(len); - args.unshift(startRow, 0); - lineWidgets.splice.apply(lineWidgets, args); - this.$updateRows(); - } - }; - - this.$updateRows = function() { - var lineWidgets = this.session.lineWidgets; - if (!lineWidgets) return; - var noWidgets = true; - lineWidgets.forEach(function(w, i) { - if (w) { - noWidgets = false; - w.row = i; - } - }); - if (noWidgets) - this.session.lineWidgets = null; - }; - - this.addLineWidget = function(w) { - if (!this.session.lineWidgets) - this.session.lineWidgets = new Array(this.session.getLength()); - - this.session.lineWidgets[w.row] = w; - - var renderer = this.editor.renderer; - if (w.html && !w.el) { - w.el = dom.createElement("div"); - w.el.innerHTML = w.html; - } - if (w.el) { - dom.addCssClass(w.el, "ace_lineWidgetContainer"); - w.el.style.position = "absolute"; - w.el.style.zIndex = 5; - renderer.container.appendChild(w.el); - w._inDocument = true; - } - - if (!w.coverGutter) { - w.el.style.zIndex = 3; - } - if (!w.pixelHeight) { - w.pixelHeight = w.el.offsetHeight; - } - if (w.rowCount == null) - w.rowCount = w.pixelHeight / renderer.layerConfig.lineHeight; - - this.session._emit("changeFold", {data:{start:{row: w.row}}}); - - this.$updateRows(); - this.renderWidgets(null, renderer); - return w; - }; - - this.removeLineWidget = function(w) { - w._inDocument = false; - if (w.el && w.el.parentNode) - w.el.parentNode.removeChild(w.el); - if (w.editor && w.editor.destroy) try { - w.editor.destroy(); - } catch(e){} - if (this.session.lineWidgets) - this.session.lineWidgets[w.row] = undefined; - this.session._emit("changeFold", {data:{start:{row: w.row}}}); - this.$updateRows(); - }; - - this.onWidgetChanged = function(w) { - this.session._changedWidgets.push(w); - this.editor && this.editor.renderer.updateFull(); - }; - - this.measureWidgets = function(e, renderer) { - var changedWidgets = this.session._changedWidgets; - var config = renderer.layerConfig; - - if (!changedWidgets || !changedWidgets.length) return; - var min = Infinity; - for (var i = 0; i < changedWidgets.length; i++) { - var w = changedWidgets[i]; - if (!w._inDocument) { - w._inDocument = true; - renderer.container.appendChild(w.el); - } - - w.h = w.el.offsetHeight; - - if (!w.fixedWidth) { - w.w = w.el.offsetWidth; - w.screenWidth = Math.ceil(w.w / config.characterWidth); - } - - var rowCount = w.h / config.lineHeight; - if (w.coverLine) { - rowCount -= this.session.getRowLineCount(w.row); - if (rowCount < 0) - rowCount = 0; - } - if (w.rowCount != rowCount) { - w.rowCount = rowCount; - if (w.row < min) - min = w.row; - } - } - if (min != Infinity) { - this.session._emit("changeFold", {data:{start:{row: min}}}); - this.session.lineWidgetWidth = null; - } - this.session._changedWidgets = []; - }; - - this.renderWidgets = function(e, renderer) { - var config = renderer.layerConfig; - var lineWidgets = this.session.lineWidgets; - if (!lineWidgets) - return; - var first = Math.min(this.firstRow, config.firstRow); - var last = Math.max(this.lastRow, config.lastRow, lineWidgets.length); - - while (first > 0 && !lineWidgets[first]) - first--; - - this.firstRow = config.firstRow; - this.lastRow = config.lastRow; - - renderer.$cursorLayer.config = config; - for (var i = first; i <= last; i++) { - var w = lineWidgets[i]; - if (!w || !w.el) continue; - - if (!w._inDocument) { - w._inDocument = true; - renderer.container.appendChild(w.el); - } - var top = renderer.$cursorLayer.getPixelPosition({row: i, column:0}, true).top; - if (!w.coverLine) - top += config.lineHeight * this.session.getRowLineCount(w.row); - w.el.style.top = top - config.offset + "px"; - - var left = w.coverGutter ? 0 : renderer.gutterWidth; - if (!w.fixedWidth) - left -= renderer.scrollLeft; - w.el.style.left = left + "px"; - - if (w.fixedWidth) { - w.el.style.right = renderer.scrollBar.getWidth() + "px"; - } else { - w.el.style.right = ""; - } - } - }; - -}).call(LineWidgets.prototype); - - -exports.LineWidgets = LineWidgets; - -}); - - - - diff --git a/lib/ace/mode/_test/highlight_rules_test.js b/lib/ace/mode/_test/highlight_rules_test.js index c3b877ec..be6656d8 100644 --- a/lib/ace/mode/_test/highlight_rules_test.js +++ b/lib/ace/mode/_test/highlight_rules_test.js @@ -1,70 +1,23 @@ var fs = require("fs"); -var path = require("path"); if (!fs.existsSync) - fs.existsSync = path.existsSync; + fs.existsSync = require("path").existsSync; require("amd-loader"); var cwd = __dirname + "/"; -var root = path.normalize(cwd + Array(5).join("../")); - -function jsFileList(path, filter) { - if (!filter) filter = /_test/; - return fs.readdirSync(path).map(function(x) { - if (x.slice(-3) == ".js" && !filter.test(x) && !/\s/.test(x)) - return x.slice(0, -3); - }).filter(Boolean); -} - -function modeList() { - return jsFileList(cwd + "../", /_highlight_rules|_test|_worker|xml_util|_outdent|behaviour|completions/); -} - -function checkModes() { - modeList().forEach(function(modeName) { - try { - var Mode = require("../" + modeName).Mode; - } catch(e) { - console.warn("Can't load mode :" + modeName, e); - return; - } - var m = new Mode(); - if (!m.lineCommentStart && !m.blockComment) - console.warn("missing comment in " + modeName); - if (!m.$id) - console.warn("missing id in " + modeName); - var tokenizer = (new Mode).getTokenizer(); - if (m.lineCommentStart) { - if (Array.isArray(m.lineCommentStart)) { - m.lineCommentStart.forEach(function(x) { - testLineComment(tokenizer, x, modeName) - }); - } else { - testLineComment(tokenizer, m.lineCommentStart, modeName) - } - } - // if (m.blockComment) { - // var tokens = tok.getLineTokens(m.lineCommentStart, "start"); - // if (!/comment/.test(tokens[0])) - // console.warn("broken lineCommentStart in " + modeName); - // } - }); - - function testLineComment(tokenizer, commentStart, modeName) { - var tokens = tokenizer.getLineTokens(commentStart + " ", "start").tokens; - if (!/comment/.test(tokens[0].type)) - console.warn("broken lineCommentStart in " + modeName); - } -} function generateTestData() { - var docRoot = root + "/demo/kitchen-sink/docs"; - var docs = fs.readdirSync(docRoot); + var root = Array(5).join("../") + "/demo/kitchen-sink/docs"; + var docs = fs.readdirSync(cwd + root); var specialDocs = fs.readdirSync(cwd); - var modes = modeList(); + var modes = fs.readdirSync(cwd + "../").filter(function(x){ + return !/(_highlight_rules|behaviour|worker)\.js$/.test(x) && /\.js$/.test(x); + }).map(function(x) { + return x.replace(/\.js$/, ""); + }); - // console.log("Docs:", docs); - // console.log("Modes:", modes); + console.log("Docs:", docs); + console.log("Modes:", modes); docs.forEach(function(docName) { var p = docName.toLowerCase().split("."); @@ -80,38 +33,31 @@ function generateTestData() { var filePath = "text_" + modeName + ".txt"; if (specialDocs.indexOf(filePath) == -1) { - filePath = docRoot + "/" + docName; - } else { - filePath = cwd + filePath; + filePath = root + "/" + docName; } - var text = fs.readFileSync(filePath, "utf8"); + var text = fs.readFileSync(cwd + filePath, "utf8"); try { var Mode = require("../" + modeName).Mode; } catch(e) { console.warn("Can't load mode :" + modeName, p, e); return; } - console.log(modeName); var tokenizer = new Mode().getTokenizer(); var state = "start"; - var data = text.split(/\r\n|\r|\n/).map(function(line) { + var data = text.split(/\n|\r|\r\n/).map(function(line) { var data = tokenizer.getLineTokens(line, state); var tmp = []; tmp.push(JSON.stringify(data.state)); - var tokenizedLine = ""; data.tokens.forEach(function(x) { - tokenizedLine += x.value; tmp.push(JSON.stringify([x.type, x.value])); }); - if (tokenizedLine != line) - tmp.push(JSON.stringify(line)); state = data.state; return tmp.join(",\n "); }); - var jsonStr = "[[\n " + data.join("\n],[\n ") + "\n]]"; + jsonStr = "[[\n " + data.join("\n],[\n ") + "\n]]"; fs.writeFileSync(cwd + "tokens_" + modeName + ".json", jsonStr, "utf8"); }); } @@ -139,31 +85,29 @@ function testMode(modeName, i) { lineData.values = []; lineData.types = []; lineData.state = lineData.shift(); - var line = null; - if (typeof lineData[lineData.length - 1] == "string") - line = lineData.pop(); lineData.forEach(function(x) { lineData.types.push(x[0]); lineData.values.push(x[1]); }); - if (typeof line != "string") - line = lineData.values.join(""); + + var line = lineData.values.join(""); var tokens = tokenizer.getLineTokens(line, state); var values = tokens.tokens.map(function(x) {return x.value;}); var types = tokens.tokens.map(function(x) {return x.type;}); + var success = true; var err = testEqual([ - JSON.stringify(lineData.state), JSON.stringify(tokens.state), + lineData.state, tokens.state, lineData.types, types, lineData.values, values]); if (err) { - console.log(line); + console.log(line) throw "error"; } - state = tokens.state; + state = lineData.state; }); } function testEqual(a) { @@ -199,12 +143,10 @@ function padNumber(num, digits) { // cli var arg = process.argv[2]; if (!arg) - test(); + test() else if (/--?g(en)?/.test(arg)) generateTestData(process.argv.splice(3)); -else if (/--?c(heck)?/.test(arg)) - checkModes(process.argv.splice(3)); else if (/\d+/.test(arg)) test(parseInt(process.argv[2],10) || 0); else - testMode(arg, -1); \ No newline at end of file + testMode(arg, -1) \ No newline at end of file diff --git a/lib/ace/mode/_test/text_coffee.txt b/lib/ace/mode/_test/text_coffee.txt index 2d9ba5ad..094e61b7 100644 --- a/lib/ace/mode/_test/text_coffee.txt +++ b/lib/ace/mode/_test/text_coffee.txt @@ -42,7 +42,6 @@ class Foo extends Bar foo.static.function #!test tokenize string with interpolation a = "#{ 22 / 7 + {x: "#{a + b}"} + 2}" -" #{ "" + {} } )" """heredoc """ do -> diff --git a/lib/ace/mode/_test/text_html.txt b/lib/ace/mode/_test/text_html.txt index d2ce8aaa..64a32cb2 100644 --- a/lib/ace/mode/_test/text_html.txt +++ b/lib/ace/mode/_test/text_html.txt @@ -1,7 +1,5 @@ - -'123' - +'123' -/*this is js - not &js; diff --git a/lib/ace/mode/_test/text_ruby.txt b/lib/ace/mode/_test/text_ruby.txt index c16ff7c5..1343a270 100644 --- a/lib/ace/mode/_test/text_ruby.txt +++ b/lib/ace/mode/_test/text_ruby.txt @@ -13,7 +13,7 @@ [1, +1, -1, 12_345, 0.000_1, _, 3_1, 1_2, 1_.0, 0._1]; -{:id => ?", :key => "value", anotherKey: [x, y?]} +{:id => 34, :key => "value"} =begin =end diff --git a/lib/ace/mode/_test/tokens_abc.json b/lib/ace/mode/_test/tokens_abc.json deleted file mode 100644 index c65ae2a5..00000000 --- a/lib/ace/mode/_test/tokens_abc.json +++ /dev/null @@ -1,2207 +0,0 @@ -[[ - "start", - ["comment.line.percentage","%abc-2.1"] -],[ - "start", - ["information.keyword","H:"], - ["information.argument.string.unquoted","This file contains some example English tunes"] -],[ - "start", - ["comment.line.percentage","% note that the comments (like this one) are to highlight usages"] -],[ - "start", - ["comment.line.percentage","% and would not normally be included in such detail"] -],[ - "start", - ["information.keyword","O:"], - ["information.argument.string.unquoted","England "], - ["comment.line.percentage","% the origin of all tunes is England"] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","1 "], - ["comment.line.percentage","% tune no 1"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Dusty Miller, The "], - ["comment.line.percentage","% title"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Binny's Jig "], - ["comment.line.percentage","% an alternative title"] -],[ - "start", - ["information.keyword","C:"], - ["information.argument.string.unquoted","Trad. "], - ["comment.line.percentage","% traditional"] -],[ - "start", - ["information.keyword","R:"], - ["information.argument.string.unquoted","DH "], - ["comment.line.percentage","% double hornpipe"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted","3/4 "], - ["comment.line.percentage","% meter"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","G "], - ["comment.line.percentage","% key"] -],[ - "start", - ["pitch.constant.numeric","B"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","g"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","a"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","/2"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","/2"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","/2"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","/2"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["information.keyword","W:"], - ["information.argument.string.unquoted","Hey, the dusty miller, and his dusty coat;"] -],[ - "start", - ["information.keyword","W:"], - ["information.argument.string.unquoted","He will win a shilling, or he spend a groat."] -],[ - "start", - ["information.keyword","W:"], - ["information.argument.string.unquoted","Dusty was the coat, dusty was the colour;"] -],[ - "start", - ["information.keyword","W:"], - ["information.argument.string.unquoted","Dusty was the kiss, that I got frae the miller."] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","2"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Old Sir Simon the King"] -],[ - "start", - ["information.keyword","C:"], - ["information.argument.string.unquoted","Trad."] -],[ - "start", - ["information.keyword","S:"], - ["information.argument.string.unquoted","Offord MSS "], - ["comment.line.percentage","% from Offord manuscript"] -],[ - "start", - ["information.keyword","N:"], - ["information.argument.string.unquoted","see also Playford "], - ["comment.line.percentage","% reference note"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted","9/8"] -],[ - "start", - ["information.keyword","R:"], - ["information.argument.string.unquoted","SJ "], - ["comment.line.percentage","% slip jig"] -],[ - "start", - ["information.keyword","N:"], - ["information.argument.string.unquoted","originally in C "], - ["comment.line.percentage","% transcription note"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","G"] -],[ - "start", - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|[1"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["text","["], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","G"], - ["text","] "], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"], - ["text","\\ "], - ["comment.line.percentage","% no line-break in score"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted","12/8 "], - ["comment.line.percentage","% change of meter"] -],[ - "start", - ["barline.keyword.operator","[2"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["text","\\ "], - ["comment.line.percentage","% no line-break in score"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted","9/8 "], - ["comment.line.percentage","% change of meter"] -],[ - "start", - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|]"] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","3"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","William and Nancy"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","New Mown Hay"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Legacy, The"] -],[ - "start", - ["information.keyword","C:"], - ["information.argument.string.unquoted","Trad."] -],[ - "start", - ["information.keyword","O:"], - ["information.argument.string.unquoted","England; Gloucs; Bledington "], - ["comment.line.percentage","% place of origin"] -],[ - "start", - ["information.keyword","B:"], - ["information.argument.string.unquoted","Sussex Tune Book "], - ["comment.line.percentage","% can be found in these books"] -],[ - "start", - ["information.keyword","B:"], - ["information.argument.string.unquoted","Mally's Cotswold Morris vol.1 2"] -],[ - "start", - ["information.keyword","D:"], - ["information.argument.string.unquoted","Morris On "], - ["comment.line.percentage","% can be heard on this record"] -],[ - "start", - ["information.keyword","P:"], - ["information.argument.string.unquoted","(AB)2(AC)2A "], - ["comment.line.percentage","% play the parts in this order"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted","6/8"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","G "] -],[ - "start", - ["information.keyword.embedded","[P:"], - ["information.argument.string.unquoted","A]"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["barline.keyword.operator","|"], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","F"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["information.keyword.embedded","[P:"], - ["information.argument.string.unquoted","B]"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","c"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","F"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["comment.line.percentage","% changes of meter, using inline fields"] -],[ - "start", - ["information.keyword.embedded","[T:"], - ["information.argument.string.unquoted","Slows]"], - ["information.keyword.embedded","[M:"], - ["information.argument.string.unquoted","4/4]"], - ["information.keyword.embedded","[L:"], - ["information.argument.string.unquoted","1/4]"], - ["information.keyword.embedded","[P:"], - ["information.argument.string.unquoted","C]"], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["string.quoted","\"Em\""], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text"," "], - ["string.quoted","\"A7\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["text","\\"] -],[ - "start", - ["text"," "], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["information.keyword.embedded","[M:"], - ["information.argument.string.unquoted","3/8]"], - ["information.keyword.embedded","[L:"], - ["information.argument.string.unquoted","1/8]"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["text"," "], - ["barline.keyword.operator","|"], - ["information.keyword.embedded","[M:"], - ["information.argument.string.unquoted","6/8]"], - ["text"," "], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","c"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["string.quoted","\"C\""], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["string.quoted","\"D7\""], - ["pitch.constant.numeric","F"], - ["text"," "], - ["string.quoted","\"G\""], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","4"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","South Downs Jig"] -],[ - "start", - ["information.keyword","R:"], - ["information.argument.string.unquoted","jig"] -],[ - "start", - ["information.keyword","S:"], - ["information.argument.string.unquoted","Robert Harbron"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted","6/8"] -],[ - "start", - ["information.keyword","L:"], - ["information.argument.string.unquoted","1/8"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","G"] -],[ - "start", - ["barline.keyword.operator","|:"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","3"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","e"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["barline.keyword.operator","|"] -],[ - "start", - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","3"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["text"," "], - ["barline.keyword.operator",":|"] -],[ - "start", - ["pitch.constant.numeric","B"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["information.keyword.embedded","[M:"], - ["information.argument.string.unquoted","9/8]"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","3"], - ["text"," "], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword.embedded","[M:"], - ["information.argument.string.unquoted","6/8]"], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","3"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","D"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text"," "], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["barline.keyword.operator","|1"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["text"," "], - ["barline.keyword.operator",":|2"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","3"], - ["text"," "], - ["barline.keyword.operator","|]"] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","5"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Atholl Brose"] -],[ - "start", - ["comment.line.percentage","% in this example, which reproduces Highland Bagpipe gracing,"] -],[ - "start", - ["comment.line.percentage","% the large number of grace notes mean that it is more convenient to be specific about"] -],[ - "start", - ["comment.line.percentage","% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them"] -],[ - "start", - ["information.keyword","I:"], - ["information.argument.string.unquoted","linebreak $"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","D"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["text","{"], - ["pitch.constant.numeric","e"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","A"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["text","{"], - ["pitch.constant.numeric","e"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","f"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["text","{"], - ["pitch.constant.numeric","e"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","A"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric",">"], - ["text","{"], - ["pitch.constant.numeric","d"], - ["text","}"], - ["pitch.constant.numeric","B"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","G"], - ["text"," {"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["text","}"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator",":|"], - ["text","$"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric","2"], - ["text"," {"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","f"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","d"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","d"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","d"], - ["text","}"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","<"], - ["text","{"], - ["pitch.constant.numeric","e"], - ["text","}"], - ["pitch.constant.numeric","G"], - ["text"," {"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["text","}"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric","2"], - ["text"," {"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","<"], - ["text","{"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","G"], - ["text","}"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","a"], - ["text"," {"], - ["pitch.constant.numeric","f"], - ["text","}"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","e"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"] -],[ - "start", - ["text","{"], - ["pitch.constant.numeric","g"], - ["text","}"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","g"], - ["text"," {"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["text","}"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","c"], - ["text"," {"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","d"], - ["text","}"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","<"], - ["text","{"], - ["pitch.constant.numeric","e"], - ["text","}"], - ["pitch.constant.numeric","G"], - ["text"," {"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["text","}"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|]"] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","6"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Untitled Reel"] -],[ - "start", - ["information.keyword","C:"], - ["information.argument.string.unquoted","Trad."] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","D"] -],[ - "start", - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","g"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","b"], - ["text"," "], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","g"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","b"], - ["pitch.constant.numeric","g"], - ["text"," "], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"], - ["text","\\"] -],[ - "start", - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","G"] -],[ - "start", - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|"] -],[ - "start" -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted","7"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted","Kitchen Girl"] -],[ - "start", - ["information.keyword","C:"], - ["information.argument.string.unquoted","Trad."] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","D"] -],[ - "start", - ["text","["], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","4"], - ["pitch.constant.numeric","a"], - ["duration.constant.numeric","4"], - ["text","] ["], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","4"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","4"], - ["text","]"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","g"], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","b"], - ["pitch.constant.numeric","a"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","g"], - ["barline.keyword.operator","|"] -],[ - "start", - ["pitch.constant.numeric","a"], - ["duration.constant.numeric","4"], - ["text"," "], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","4"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","4"], - ["barline.keyword.operator",":|"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted","G"] -],[ - "start", - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","D"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","3"], - ["pitch.constant.numeric","f"], - ["text"," "], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"] -],[ - "start", - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["text"," "], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","4"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","4"], - ["barline.keyword.operator",":|"] -],[ - "start" -],[ - "start", - ["comment.line.percentage","%abc-2.1"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","pagewidth 21cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","pageheight 29.7cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","topspace 0.5cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","topmargin 1cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","botmargin 0cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","leftmargin 1cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","rightmargin 1cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","titlespace 0cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","titlefont Times-Bold 32"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","subtitlefont Times-Bold 24"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","composerfont Times 16"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","vocalfont Times-Roman 14"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","staffsep 60pt"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","sysstaffsep 20pt"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","musicspace 1cm"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","vocalspace 5pt"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","measurenb 0"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","barsperstaff 5"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","scale 0.7"] -],[ - "start", - ["information.keyword","X:"], - ["information.argument.string.unquoted"," 1"] -],[ - "start", - ["information.keyword","T:"], - ["information.argument.string.unquoted"," Canzonetta a tre voci"] -],[ - "start", - ["information.keyword","C:"], - ["information.argument.string.unquoted"," Claudio Monteverdi (1567-1643)"] -],[ - "start", - ["information.keyword","M:"], - ["information.argument.string.unquoted"," C"] -],[ - "start", - ["information.keyword","L:"], - ["information.argument.string.unquoted"," 1/4"] -],[ - "start", - ["information.keyword","Q:"], - ["information.argument.string.unquoted"," \"Andante mosso\" 1/4 = 110"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","score [1 2 3]"] -],[ - "start", - ["information.keyword","V:"], - ["information.argument.string.unquoted"," 1 clef=treble name=\"Soprano\"sname=\"A\""] -],[ - "start", - ["information.keyword","V:"], - ["information.argument.string.unquoted"," 2 clef=treble name=\"Alto\" sname=\"T\""] -],[ - "start", - ["information.keyword","V:"], - ["information.argument.string.unquoted"," 3 clef=bass middle=d name=\"Tenor\" sname=\"B\""] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","MIDI program 1 75 % recorder"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","MIDI program 2 75"] -],[ - "start", - ["information.comment.line.percentage","%%"], - ["information.keyword.embedded","MIDI program 3 75"] -],[ - "start", - ["information.keyword","K:"], - ["information.argument.string.unquoted"," Eb"] -],[ - "start", - ["comment.line.percentage","% 1 - 4"] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 1]"], - ["text"," "], - ["barline.keyword.operator","|:"], - ["pitch.constant.numeric","z"], - ["duration.constant.numeric","4"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","z"], - ["duration.constant.numeric","4"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["barline.keyword.operator","|"], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," Son que-sti~i cre-spi cri-ni~e"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," Que-sti son gli~oc-chi che mi-"] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 2]"], - ["text"," "], - ["barline.keyword.operator","|:"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","c"], - ["barline.keyword.operator","|"], - ["text","("], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","/"], - ["text",")"], - ["pitch.constant.numeric","c"], - ["accent.constant.language","="], - ["pitch.constant.numeric","A"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi-"] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 3]"], - ["text"," "], - ["barline.keyword.operator","|:"], - ["pitch.constant.numeric","z"], - ["duration.constant.numeric","4"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["barline.keyword.operator","|"], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","f"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text","("], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","/"], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","/"], - ["text",")"], - ["pitch.constant.numeric","f"], - ["pitch.constant.numeric","f"], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," Son que-sti~i cre-spi cri-ni~e que - - - - sto~il"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," Que-sti son~gli oc-chi che mi-ran - - - - do"] -],[ - "start", - ["comment.line.percentage","% 5 - 9"] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 1]"], - ["text"," "], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","3"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["string.quoted","!fermata!"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","z"], - ["text"," "], - ["barline.keyword.operator","::"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","4"], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," ran-do fi-so, tut-to re-stai con-qui-so."] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 2]"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","3"], - ["pitch.constant.numeric","F"], - ["barline.keyword.operator","|"], - ["accent.constant.language","="], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","2"], - ["string.quoted","!fermata!"], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","z"], - ["barline.keyword.operator","::"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","4"], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," ran-do fi-so tut-to re-stai con-qui-so."] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 3]"], - ["text"," ("], - ["pitch.constant.numeric","a"], - ["pitch.constant.numeric","g"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","f"], - ["duration.constant.numeric","/"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["text",")"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","3"], - ["pitch.constant.numeric","B"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["string.quoted","!fermata!"], - ["pitch.constant.numeric","c"], - ["pitch.constant.numeric","z"], - ["text"," "], - ["barline.keyword.operator","::"], - ["pitch.constant.numeric","A"], - ["duration.constant.numeric","4"], - ["barline.keyword.operator","|"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," vi - - - so ond' io ti-man-go~uc-ci-so. Deh,"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," fi - - - so tut-to re-stai con-qui-so."] -],[ - "start", - ["comment.line.percentage","% 10 - 15"] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 1]"], - ["text"," "], - ["pitch.constant.numeric","f"], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","e"], - ["pitch.constant.numeric","c"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","B"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","z"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text","\\"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," dim-me-lo ben mi-o, che que-sto"], - ["text","\\"] -],[ - "start", - ["accent.constant.language","="], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["text"," "], - ["barline.keyword.operator","|1"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","z"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|2"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","8"], - ["barline.keyword.operator","|]"], - ["text"," "], - ["comment.line.percentage","% more notes"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," sol de-si-o_. "], - ["comment.line.percentage","% more lyrics"] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 2]"], - ["text"," "], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","A"], - ["text"," "], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","A"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["accent.constant.language","="], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["text"," "], - ["barline.keyword.operator","|"], - ["text","("], - ["pitch.constant.numeric","G"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","3/2"], - ["accent.constant.language","="], - ["pitch.constant.numeric","E"], - ["duration.constant.numeric","//"], - ["pitch.constant.numeric","D"], - ["duration.constant.numeric","//"], - ["pitch.constant.numeric","E"], - ["text",")"], - ["barline.keyword.operator","|1"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","z"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|2"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","8"], - ["barline.keyword.operator","|]"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_."] -],[ - "start", - ["information.keyword.embedded","[V:"], - ["information.argument.string.unquoted"," 3]"], - ["text"," "], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["pitch.constant.numeric","B"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric",">"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","e"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","A"], - ["pitch.constant.numeric","F"], - ["barline.keyword.operator","|"], - ["accent.constant.language","="], - ["pitch.constant.numeric","E"], - ["pitch.constant.numeric","F"], - ["pitch.constant.numeric","c"], - ["accent.constant.language","_"], - ["pitch.constant.numeric","d"], - ["barline.keyword.operator","|"], - ["pitch.constant.numeric","c"], - ["duration.constant.numeric","4"], - ["text"," "], - ["barline.keyword.operator","|1"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","2"], - ["pitch.constant.numeric","z"], - ["duration.constant.numeric","2"], - ["barline.keyword.operator",":|2"], - ["pitch.constant.numeric","F"], - ["duration.constant.numeric","8"], - ["barline.keyword.operator","|]"] -],[ - "start", - ["information.keyword","w:"], - ["information.argument.string.unquoted"," dim-me-lo ben mi-o, che que-sto sol de-si-o_."] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_ada.json b/lib/ace/mode/_test/tokens_ada.json deleted file mode 100644 index bdef7256..00000000 --- a/lib/ace/mode/_test/tokens_ada.json +++ /dev/null @@ -1,39 +0,0 @@ -[[ - "start", - ["keyword","with"], - ["text"," "], - ["identifier","Ada"], - ["text","."], - ["identifier","Text_IO"], - ["text","; "], - ["keyword","use"], - ["text"," "], - ["identifier","Ada"], - ["text","."], - ["identifier","Text_IO"], - ["text",";"] -],[ - "start", - ["keyword","procedure"], - ["text"," "], - ["identifier","Hello"], - ["text"," "], - ["keyword","is"] -],[ - "start", - ["keyword","begin"] -],[ - "start", - ["text"," "], - ["identifier","Put_Line"], - ["paren.lparen","("], - ["string","\"Hello, world!\""], - ["paren.rparen",")"], - ["text",";"] -],[ - "start", - ["keyword","end"], - ["text"," "], - ["identifier","Hello"], - ["text",";"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_c9search.json b/lib/ace/mode/_test/tokens_c9search.json index 902d8dce..98052746 100644 --- a/lib/ace/mode/_test/tokens_c9search.json +++ b/lib/ace/mode/_test/tokens_c9search.json @@ -1,131 +1,104 @@ [[ - ["start",{}], - ["text","Searching for '"], - ["text","var"], - ["text","' in"], - ["text"," /.c9/metadata/workspace/plugins "], - ["text","(regexp, case sensitive, whole word)"], - "Searching for \u0001var\u0001 in\u0001/.c9/metadata/workspace/plugins\u0001\u0001regexp, case sensitive, whole word\u0001" + "start", + ["text","Searching for 'var' in /workspace/configs"] ],[ - ["start",{}] + "start" ],[ - ["start",{}], + "start", ["string","configs/default.js"], ["text",":"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric"," 1"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," fs = require(\"fs\");"] + ["c9searchresults.text","var fs = require(\"fs\");"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t2"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," argv = require('optimist').argv;"] + ["c9searchresults.text","var argv = require('optimist').argv;"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t3"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," path = require(\"path\");"] + ["c9searchresults.text","var path = require(\"path\");"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t5"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," clientExtensions = {};"] + ["c9searchresults.text","var clientExtensions = {};"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t6"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," clientDirs = fs.readdirSync(__dirname + \"/../plugins-client\");"] + ["c9searchresults.text","var clientDirs = fs.readdirSync(__dirname + \"/../plugins-client\");"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t7"], ["c9searchresults.text",": "], - ["c9searchresults.text","for ("], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," i = 0; i < clientDirs.length; i++) {"] + ["c9searchresults.text","for (var i = 0; i < clientDirs.length; i++) {"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t8"], - ["c9searchresults.text",": "], - ["c9searchresults.text"," "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," dir = clientDirs[i];"] + ["c9searchresults.text",": "], + ["c9searchresults.text","var dir = clientDirs[i];"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t12"], - ["c9searchresults.text",": "], - ["c9searchresults.text"," "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," name = dir.split(\".\")[1];"] + ["c9searchresults.text",": "], + ["c9searchresults.text","var name = dir.split(\".\")[1];"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t16"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," projectDir = (argv.w && path.resolve(process.cwd(), argv.w)) || process.cwd();"] + ["c9searchresults.text","var projectDir = (argv.w && path.resolve(process.cwd(), argv.w)) || process.cwd();"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t17"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," fsUrl = \"/workspace\";"] + ["c9searchresults.text","var fsUrl = \"/workspace\";"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t19"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," port = argv.p || process.env.PORT || 3131;"] + ["c9searchresults.text","var port = argv.p || process.env.PORT || 3131;"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t20"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," host = argv.l || \"localhost\";"] + ["c9searchresults.text","var host = argv.l || \"localhost\";"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t22"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," config = {"] + ["c9searchresults.text","var config = {"] ],[ - ["start",{}] + "start" ],[ - ["start",{}], + "start", ["string","configs/local.js"], ["text",":"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t2"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," config = require(\"./default\");"] + ["c9searchresults.text","var config = require(\"./default\");"] ],[ - ["start",{}] + "start" ],[ - ["start",{}], + "start", ["string","configs/packed.js"], ["text",":"] ],[ - ["start",{}], + "start", ["c9searchresults.constant.numeric","\t1"], ["c9searchresults.text",": "], - ["c9searchresults.keyword","var"], - ["c9searchresults.text"," config = require(\"./default\");"] + ["c9searchresults.text","var config = require(\"./default\");"] ],[ - ["start",{}] + "start" ],[ - ["start",{}] + "start" ],[ - ["start",{}], - ["text","Found "], - ["constant.numeric","15"], - ["text"," matches in "], - ["constant.numeric","3"], - ["text"," files"] + "start", + ["text","Found 15 matches in 3 files"] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_c_cpp.json b/lib/ace/mode/_test/tokens_c_cpp.json index a8668b0b..2818526f 100644 --- a/lib/ace/mode/_test/tokens_c_cpp.json +++ b/lib/ace/mode/_test/tokens_c_cpp.json @@ -137,12 +137,7 @@ "start", ["text"," "], ["keyword","#if"], - ["text"," "], - ["identifier","VERBOSE"], - ["text"," "], - ["keyword.operator",">="], - ["text"," "], - ["constant.numeric","2"] + ["constant.other"," VERBOSE >= 2"] ],[ "start", ["text"," "], diff --git a/lib/ace/mode/_test/tokens_cirru.json b/lib/ace/mode/_test/tokens_cirru.json deleted file mode 100644 index de4852e6..00000000 --- a/lib/ace/mode/_test/tokens_cirru.json +++ /dev/null @@ -1,267 +0,0 @@ -[[ - "start", - ["comment.line.double-dash","-- https://github.com/Cirru/cirru-gopher/blob/master/code/scope.cr,"] -],[ - "start" -],[ - "line", - ["support.function","set"], - ["text"," "], - ["variable.parameter","a"], - ["text"," "], - ["storage.modifier","("], - ["support.function","int"], - ["text"," "], - ["constant.numeric","2"], - ["storage.modifier",")"] -],[ - "start" -],[ - "line", - ["support.function","print"], - ["text"," "], - ["storage.modifier","("], - ["support.function","self"], - ["storage.modifier",")"] -],[ - "start" -],[ - "line", - ["support.function","set"], - ["text"," "], - ["variable.parameter","c"], - ["text"," "], - ["storage.modifier","("], - ["support.function","child"], - ["storage.modifier",")"] -],[ - "start" -],[ - "line", - ["support.function","under"], - ["text"," "], - ["variable.parameter","c"] -],[ - "line", - ["markup.raw"," "], - ["support.function","under"], - ["text"," "], - ["variable.parameter","parent"] -],[ - "line", - ["markup.raw"," "], - ["support.function","print"], - ["text"," "], - ["variable.parameter","a"] -],[ - "start" -],[ - "line", - ["support.function","print"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","get"], - ["text"," "], - ["variable.parameter","c"], - ["text"," "], - ["variable.parameter","a"] -],[ - "start" -],[ - "line", - ["support.function","set"], - ["text"," "], - ["variable.parameter","c"], - ["text"," "], - ["variable.parameter","x"], - ["text"," "], - ["storage.modifier","("], - ["support.function","int"], - ["text"," "], - ["constant.numeric","3"], - ["storage.modifier",")"] -],[ - "line", - ["support.function","print"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","get"], - ["text"," "], - ["variable.parameter","c"], - ["text"," "], - ["variable.parameter","x"] -],[ - "start" -],[ - "line", - ["support.function","set"], - ["text"," "], - ["variable.parameter","just-print"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","code"] -],[ - "line", - ["markup.raw"," "], - ["support.function","print"], - ["text"," "], - ["variable.parameter","a"] -],[ - "start" -],[ - "line", - ["support.function","print"], - ["text"," "], - ["variable.parameter","just-print"] -],[ - "start" -],[ - "line", - ["support.function","eval"], - ["text"," "], - ["storage.modifier","("], - ["support.function","self"], - ["storage.modifier",")"], - ["text"," "], - ["variable.parameter","just-print"] -],[ - "line", - ["support.function","eval"], - ["text"," "], - ["variable.parameter","just-print"] -],[ - "start" -],[ - "line", - ["support.function","print"], - ["text"," "], - ["storage.modifier","("], - ["support.function","string"], - ["text"," "], - ["string.quoted.double","\"string with space\""], - ["storage.modifier",")"] -],[ - "line", - ["support.function","print"], - ["text"," "], - ["storage.modifier","("], - ["support.function","string"], - ["text"," "], - ["string.quoted.double","\"escapes "], - ["constant.character.escape","\\n"], - ["string.quoted.double"," "], - ["constant.character.escape","\\\"\\\\"], - ["string.quoted.double","\""], - ["storage.modifier",")"] -],[ - "start" -],[ - "start", - ["support.function","brackets"], - ["text"," "], - ["storage.modifier","((((()))))"] -],[ - "start" -],[ - "line", - ["string.quoted.double","\"eval\""], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","string"], - ["text"," "], - ["string.quoted.double","\"eval\""] -],[ - "start" -],[ - "line", - ["support.function","print"], - ["text"," "], - ["storage.modifier","("], - ["support.function","add"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["storage.modifier","("], - ["support.function","int"], - ["text"," "], - ["constant.numeric","1"], - ["storage.modifier",")"], - ["text"," "], - ["storage.modifier","("], - ["support.function","int"], - ["text"," "], - ["constant.numeric","2"], - ["storage.modifier","))"] -],[ - "start" -],[ - "start", - ["support.function","print"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","unwrap"], - ["text"," "], - ["storage.modifier","$"] -],[ - "line", - ["text"," "], - ["support.function","map"], - ["text"," "], - ["storage.modifier","("], - ["support.function","a"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","int"], - ["text"," "], - ["constant.numeric","1"], - ["storage.modifier",")"], - ["text"," "], - ["storage.modifier","("], - ["support.function","b"], - ["text"," "], - ["storage.modifier","$"], - ["text"," "], - ["support.function","int"], - ["text"," "], - ["constant.numeric","2"], - ["storage.modifier",")"] -],[ - "start" -],[ - "line", - ["support.function","print"], - ["text"," "], - ["variable.parameter","a"] -],[ - "line", - ["markup.raw"," "], - ["support.function","int"], - ["text"," "], - ["constant.numeric","1"] -],[ - "line", - ["markup.raw"," "], - ["storage.modifier",","], - ["text"," "], - ["variable.parameter","b"], - ["text"," "], - ["variable.parameter","c"] -],[ - "line", - ["markup.raw"," "], - ["support.function","int"], - ["text"," "], - ["constant.numeric","2"] -],[ - "line", - ["markup.raw"," "], - ["storage.modifier",","], - ["text"," "], - ["variable.parameter","d"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_cobol.json b/lib/ace/mode/_test/tokens_cobol.json deleted file mode 100644 index 9909eadd..00000000 --- a/lib/ace/mode/_test/tokens_cobol.json +++ /dev/null @@ -1,4 +0,0 @@ -[[ - "start", - ["identifier","TODO"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_coffee.json b/lib/ace/mode/_test/tokens_coffee.json index b0703b37..9c3967e4 100644 --- a/lib/ace/mode/_test/tokens_coffee.json +++ b/lib/ace/mode/_test/tokens_coffee.json @@ -466,23 +466,6 @@ ["constant.numeric","2"], ["paren.string","}"], ["string.end","\""] -],[ - "start", - ["string.start","\""], - ["string"," "], - ["paren.string","#{"], - ["text"," "], - ["string.start","\""], - ["string.end","\""], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["paren","{}"], - ["text"," "], - ["paren.string","}"], - ["string"," )"], - ["string.end","\""], - ["text"," "] ],[ "qqdoc", ["string","\"\"\"heredoc"] diff --git a/lib/ace/mode/_test/tokens_coldfusion.json b/lib/ace/mode/_test/tokens_coldfusion.json index 804e647d..02f2c3f7 100644 --- a/lib/ace/mode/_test/tokens_coldfusion.json +++ b/lib/ace/mode/_test/tokens_coldfusion.json @@ -1,26 +1,26 @@ [[ "start", - ["comment.xml",""] + ["comment",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","cfset"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","welcome"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"Hello World!\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","cfset"], + ["text"," "], + ["entity.other.attribute-name","welcome"], + ["keyword.operator.separator","="], + ["string","\"Hello World!\""], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","cfoutput"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","#welcome#"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","cfoutput"], + ["meta.tag.punctuation.end",">"], + ["text","#welcome#"], + ["meta.tag.punctuation.begin",""] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_curly.json b/lib/ace/mode/_test/tokens_curly.json index d87a627a..110574b6 100644 --- a/lib/ace/mode/_test/tokens_curly.json +++ b/lib/ace/mode/_test/tokens_curly.json @@ -1,56 +1,56 @@ [[ "start", - ["text.xml","tokenize Curly template"], + ["text","tokenize Curly template"], ["variable","{{"], ["text","test"], ["variable","}}"] ],[ "start", - ["text.xml","tokenize embedded script"] + ["text","tokenize embedded script"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.script.tag-name.xml","script"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","a"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","'a'"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.script","script"], + ["text"," "], + ["entity.other.attribute-name","a"], + ["keyword.operator.separator","="], + ["string","'a'"], + ["meta.tag.punctuation.end",">"], ["storage.type","var"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml","'123'"] + ["meta.tag.punctuation.begin",""], + ["text","'123'"] ],[ "start", - ["text.xml","tokenize multiline attribute value with double quotes"] + ["text","tokenize multiline attribute value with double quotes"] ],[ - ["string.attribute-value.xml0","tag_stuff"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"abc{{xyz}}"] + ["qqstring_inner","start_tag_stuff"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\"abc{{xyz}}"] ],[ "start", - ["string.attribute-value.xml","def\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["string","def\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml","tokenize multiline attribute value with single quotes"] + ["text","tokenize multiline attribute value with single quotes"] ],[ - ["string.attribute-value.xml","tag_stuff"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","'abc"] + ["qstring_inner","start_tag_stuff"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","'abc"] ],[ "start", - ["string.attribute-value.xml","def\\\"'"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["string","def\\\"'"], + ["meta.tag.punctuation.end",">"] ],[ "start" ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_d.json b/lib/ace/mode/_test/tokens_d.json deleted file mode 100644 index 85831cc3..00000000 --- a/lib/ace/mode/_test/tokens_d.json +++ /dev/null @@ -1,111 +0,0 @@ -[[ - "start", - ["comment.shebang","#!/usr/bin/env rdmd"] -],[ - "start", - ["comment","// Computes average line length for standard input."] -],[ - "start", - ["keyword","import"], - ["text"," "], - ["variable.module","std.stdio"], - ["punctuation.operator",";"] -],[ - "start" -],[ - "start", - ["keyword.type","void"], - ["text"," "], - ["identifier","main"], - ["paren.lparen","("], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword.type","ulong"], - ["text"," "], - ["identifier","lines"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["constant.numeric","0"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["keyword.type","double"], - ["text"," "], - ["identifier","sumLength"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["constant.numeric","0"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["keyword.control","foreach"], - ["text"," "], - ["paren.lparen","("], - ["identifier","line"], - ["punctuation.operator",";"], - ["text"," "], - ["identifier","stdin"], - ["punctuation.operator","."], - ["identifier","byLine"], - ["paren.lparen","("], - ["paren.rparen","))"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword.operator","++"], - ["identifier","lines"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["identifier","sumLength"], - ["text"," "], - ["keyword.operator","+="], - ["text"," "], - ["identifier","line"], - ["punctuation.operator","."], - ["identifier","length"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["identifier","writeln"], - ["paren.lparen","("], - ["string","\"Average line length: \""], - ["punctuation.operator",","] -],[ - "start", - ["text"," "], - ["identifier","lines"], - ["text"," "], - ["keyword.operator","?"], - ["text"," "], - ["identifier","sumLength"], - ["text"," "], - ["keyword.operator","/"], - ["text"," "], - ["identifier","lines"], - ["text"," "], - ["punctuation.operator",":"], - ["text"," "], - ["constant.numeric","0"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start", - ["paren.rparen","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_dart.json b/lib/ace/mode/_test/tokens_dart.json index 37cdc323..5964791a 100644 --- a/lib/ace/mode/_test/tokens_dart.json +++ b/lib/ace/mode/_test/tokens_dart.json @@ -330,7 +330,7 @@ ["text",";"] ],[ "start", - ["keyword.control.dart","assert"], + ["identifier","assert"], ["text","("], ["identifier","unicorn"], ["text"," "], @@ -357,7 +357,7 @@ ["text",";"] ],[ "start", - ["keyword.control.dart","assert"], + ["identifier","assert"], ["text","("], ["identifier","iMeantToDoThis"], ["text","."], diff --git a/lib/ace/mode/_test/tokens_diff.json b/lib/ace/mode/_test/tokens_diff.json index 6c36f5fa..7cf9b728 100644 --- a/lib/ace/mode/_test/tokens_diff.json +++ b/lib/ace/mode/_test/tokens_diff.json @@ -4,257 +4,393 @@ ["variable"," --git"], ["keyword"," a/lib/ace/edit_session.js"], ["variable"," b/lib/ace/edit_session.js"] +],[ + "start" ],[ "start", ["variable","index 23fc3fc..ed3b273 100644"] +],[ + "start" ],[ "start", ["constant.numeric","---"], ["meta.tag"," a/lib/ace/edit_session.js"] +],[ + "start" ],[ "start", ["constant.numeric","+++"], ["meta.tag"," b/lib/ace/edit_session.js"] +],[ + "start" ],[ "start", ["constant","@@"], ["constant.numeric"," -51,6 +51,7 "], ["constant","@@"], ["comment.doc.tag"," var TextMode = require(\"./mode/text\").Mode;"] +],[ + "start" ],[ "start", ["invisible"," var Range = require(\"./range\").Range;"] +],[ + "start" ],[ "start", ["invisible"," var Document = require(\"./document\").Document;"] +],[ + "start" ],[ "start", ["invisible"," var BackgroundTokenizer = require(\"./background_tokenizer\").BackgroundTokenizer;"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text","var SearchHighlight = require(\"./search_highlight\").SearchHighlight;"] +],[ + "start" ],[ "start", ["text"," "] +],[ + "start" ],[ "start", ["invisible"," /**"] +],[ + "start" ],[ "start", ["invisible"," * class EditSession"] +],[ + "start" ],[ "start", ["constant","@@"], ["constant.numeric"," -307,6 +308,13 "], ["constant","@@"], ["comment.doc.tag"," var EditSession = function(text, mode) {"] +],[ + "start" ],[ "start", ["invisible"," return token;"] +],[ + "start" ],[ "start", ["invisible"," };"] +],[ + "start" ],[ "start", ["text"," "] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," this.highlight = function(re) {"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," if (!this.$searchHighlight) {"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," var highlight = new SearchHighlight(null, \"ace_selected-word\", \"text\");"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," this.$searchHighlight = this.addDynamicMarker(highlight);"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," }"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," this.$searchHighlight.setRegexp(re);"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," }"] +],[ + "start" ],[ "start", ["invisible"," /**"] +],[ + "start" ],[ "start", ["invisible"," * EditSession.setUndoManager(undoManager)"] +],[ + "start" ],[ "start", ["invisible"," * - undoManager (UndoManager): The new undo manager"] +],[ + "start" ],[ "start", ["constant","@@"], ["constant.numeric"," -556,7 +564,8 "], ["constant","@@"], ["comment.doc.tag"," var EditSession = function(text, mode) {"] +],[ + "start" ],[ "start", ["invisible"," type : type || \"line\","] +],[ + "start" ],[ "start", ["invisible"," renderer: typeof type == \"function\" ? type : null,"] +],[ + "start" ],[ "start", ["invisible"," clazz : clazz,"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," inFront: !!inFront"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," inFront: !!inFront,"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," id: id"] +],[ + "start" ],[ "start", ["invisible"," }"] +],[ + "start" ],[ "start", ["text"," "] +],[ + "start" ],[ "start", ["invisible"," if (inFront) {"] +],[ + "start" ],[ "start", ["variable","diff"], ["variable"," --git"], ["keyword"," a/lib/ace/editor.js"], ["variable"," b/lib/ace/editor.js"] +],[ + "start" ],[ "start", ["variable","index 834e603..b27ec73 100644"] +],[ + "start" ],[ "start", ["constant.numeric","---"], ["meta.tag"," a/lib/ace/editor.js"] +],[ + "start" ],[ "start", ["constant.numeric","+++"], ["meta.tag"," b/lib/ace/editor.js"] +],[ + "start" ],[ "start", ["constant","@@"], ["constant.numeric"," -494,7 +494,7 "], ["constant","@@"], ["comment.doc.tag"," var Editor = function(renderer, session) {"] +],[ + "start" ],[ "start", ["invisible"," * Emitted when a selection has changed."] +],[ + "start" ],[ "start", ["invisible"," **/"] +],[ + "start" ],[ "start", ["invisible"," this.onSelectionChange = function(e) {"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," var session = this.getSession();"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," var session = this.session;"] +],[ + "start" ],[ "start", ["text"," "] +],[ + "start" ],[ "start", ["invisible"," if (session.$selectionMarker) {"] +],[ + "start" ],[ "start", ["invisible"," session.removeMarker(session.$selectionMarker);"] +],[ + "start" ],[ "start", ["constant","@@"], ["constant.numeric"," -509,12 +509,40 "], ["constant","@@"], ["comment.doc.tag"," var Editor = function(renderer, session) {"] +],[ + "start" ],[ "start", ["invisible"," this.$updateHighlightActiveLine();"] +],[ + "start" ],[ "start", ["invisible"," }"] +],[ + "start" ],[ "start", ["text"," "] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," var self = this;"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," if (this.$highlightSelectedWord && !this.$wordHighlightTimer)"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," this.$wordHighlightTimer = setTimeout(function() {"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," self.session.$mode.highlightSelection(self);"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," self.$wordHighlightTimer = null;"] +],[ + "start" ],[ "start", ["support.function","-"], ["string"," }, 30, this);"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text"," var re = this.$highlightSelectedWord && this.$getSelectionHighLightRegexp()"] +],[ + "start" ],[ "start", ["invisible"," };"] +],[ + "start" ],[ "start", ["variable","diff"], ["variable"," --git"], ["keyword"," a/lib/ace/search_highlight.js"], ["variable"," b/lib/ace/search_highlight.js"] +],[ + "start" ],[ "start", ["invisible","new file mode 100644"] +],[ + "start" ],[ "start", ["variable","index 0000000..b2df779"] +],[ + "start" ],[ "start", ["constant.numeric","---"], ["meta.tag"," /dev/null"] +],[ + "start" ],[ "start", ["constant.numeric","+++"], ["meta.tag"," b/lib/ace/search_highlight.js"] +],[ + "start" ],[ "start", ["constant","@@"], ["constant.numeric"," -0,0 +1,3 "], ["constant","@@"] +],[ + "start" ],[ "start", ["support.constant","+"], ["text","new"] +],[ + "start" ],[ "start", ["support.constant","+"], diff --git a/lib/ace/mode/_test/tokens_eiffel.json b/lib/ace/mode/_test/tokens_eiffel.json deleted file mode 100644 index 344dbc62..00000000 --- a/lib/ace/mode/_test/tokens_eiffel.json +++ /dev/null @@ -1,141 +0,0 @@ -[[ - "start", - ["keyword","note"] -],[ - "start", - ["text","\t"], - ["identifier","description"], - ["keyword.operator",":"], - ["text"," "], - ["string.quoted.double","\"Represents a person.\""] -],[ - "start" -],[ - "start", - ["keyword","class"] -],[ - "start", - ["text","\t"], - ["entity.name.type","PERSON"] -],[ - "start" -],[ - "start", - ["keyword","create"] -],[ - "start", - ["text","\t"], - ["identifier","make"], - ["keyword.operator",","], - ["text"," "], - ["identifier","make_unknown"] -],[ - "start" -],[ - "start", - ["keyword","feature"], - ["text"," "], - ["paren.lparen","{"], - ["entity.name.type","NONE"], - ["paren.rparen","}"], - ["text"," "], - ["comment.line.double-dash","-- Creation"] -],[ - "start" -],[ - "start", - ["text","\t"], - ["identifier","make"], - ["text"," "], - ["paren.lparen","("], - ["identifier","a_name"], - ["keyword.operator",":"], - ["text"," "], - ["keyword","like"], - ["text"," "], - ["identifier","name"], - ["paren.rparen",")"] -],[ - "start", - ["text","\t\t\t"], - ["comment.line.double-dash","-- Create a person with `a_name' as `name'."] -],[ - "start", - ["text","\t\t"], - ["keyword","do"] -],[ - "start", - ["text","\t\t\t"], - ["identifier","name"], - ["text"," "], - ["keyword.operator",":="], - ["text"," "], - ["identifier","a_name"] -],[ - "start", - ["text","\t\t"], - ["keyword","ensure"] -],[ - "start", - ["text","\t\t\t"], - ["identifier","name"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["identifier","a_name"] -],[ - "start", - ["text","\t\t"], - ["keyword","end"] -],[ - "start" -],[ - "start", - ["text","\t"], - ["identifier","make_unknown"] -],[ - "start", - ["text","\t\t"], - ["keyword","do"], - ["text"," "], - ["keyword","ensure"] -],[ - "start", - ["text","\t\t\t"], - ["identifier","name"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["constant.language","Void"] -],[ - "start", - ["text","\t\t"], - ["keyword","end"] -],[ - "start" -],[ - "start", - ["keyword","feature"], - ["text"," "], - ["comment.line.double-dash","-- Access"] -],[ - "start" -],[ - "start", - ["text","\t"], - ["identifier","name"], - ["keyword.operator",":"], - ["text"," "], - ["keyword","detachable"], - ["text"," "], - ["entity.name.type","STRING"] -],[ - "start", - ["text","\t\t\t"], - ["comment.line.double-dash","-- Full name or Void if unknown."] -],[ - "start" -],[ - "start", - ["keyword","end"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_ejs.json b/lib/ace/mode/_test/tokens_ejs.json deleted file mode 100644 index 7e54af91..00000000 --- a/lib/ace/mode/_test/tokens_ejs.json +++ /dev/null @@ -1,296 +0,0 @@ -[[ - "start", - ["xml-pe.doctype.xml",""] -],[ - "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","head"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Cloud9 Rocks!"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","body"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start" -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","table"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"table\""], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Name"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Size"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["markup.list.meta.tag","<%"], - ["text"," "], - ["keyword","if"], - ["text"," "], - ["paren.lparen","("], - ["keyword.operator","!"], - ["identifier","isRoot"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["markup.list.meta.tag","%>"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"..\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml",".."], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["markup.list.meta.tag","<%"], - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["markup.list.meta.tag","%>"] -],[ - "start", - ["text.xml"," "], - ["markup.list.meta.tag","<%"], - ["text"," "], - ["identifier","entries"], - ["punctuation.operator","."], - ["identifier","forEach"], - ["paren.lparen","("], - ["storage.type","function"], - ["paren.lparen","("], - ["identifier","entry"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["markup.list.meta.tag","%>"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","span"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"glyphicon "], - ["markup.list.meta.tag","<%="], - ["text"," "], - ["identifier","entry"], - ["punctuation.operator","."], - ["identifier","mime"], - ["text"," "], - ["keyword.operator","=="], - ["text"," "], - ["string","'directory'"], - ["text"," "], - ["punctuation.operator","?"], - ["text"," "], - ["string","'folder'"], - ["punctuation.operator",":"], - ["text"," "], - ["string","'file'"], - ["markup.list.meta.tag","%>"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], - ["markup.list.meta.tag","<%="], - ["text"," "], - ["identifier","entry"], - ["punctuation.operator","."], - ["identifier","name"], - ["text"," "], - ["markup.list.meta.tag","%>"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["markup.list.meta.tag","<%="], - ["text"," "], - ["identifier","entry"], - ["punctuation.operator","."], - ["identifier","name"], - ["text"," "], - ["markup.list.meta.tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["markup.list.meta.tag","<%="], - ["text"," "], - ["identifier","entry"], - ["punctuation.operator","."], - ["identifier","size"], - ["text"," "], - ["markup.list.meta.tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["markup.list.meta.tag","<%"], - ["text"," "], - ["paren.rparen","})"], - ["text"," "], - ["markup.list.meta.tag","%>"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["meta.tag.punctuation.end-tag-open.xml",""] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_elixir.json b/lib/ace/mode/_test/tokens_elixir.json deleted file mode 100644 index cbbe1fee..00000000 --- a/lib/ace/mode/_test/tokens_elixir.json +++ /dev/null @@ -1,196 +0,0 @@ -[[ - "start", - ["keyword.control.module.elixir","defmodule"], - ["meta.module.elixir"," "], - ["entity.name.type.module.elixir","HelloModule"], - ["text"," "], - ["keyword.control.elixir","do"] -],[ - "comment.documentation.heredoc", - ["text"," "], - ["comment.documentation.heredoc","@moduledoc \"\"\""] -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," This is supposed to be `markdown`."] -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," __Yes__ this is [mark](http://down.format)"] -],[ - "comment.documentation.heredoc" -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," # Truly"] -],[ - "comment.documentation.heredoc" -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," ## marked"] -],[ - "comment.documentation.heredoc" -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," * with lists"] -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," * more"] -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," * and more"] -],[ - "comment.documentation.heredoc" -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," Even.with(code)"] -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," blocks |> with |> samples"] -],[ - "comment.documentation.heredoc" -],[ - "comment.documentation.heredoc", - ["comment.documentation.heredoc"," _Docs are first class citizens in Elixir_ (Jose Valim)"] -],[ - "start", - ["comment.documentation.heredoc"," \"\"\""] -],[ - "start", - ["text"," "] -],[ - "start", - ["text"," "], - ["punctuation.definition.comment.elixir","#"], - ["comment.line.number-sign.elixir"," A \"Hello world\" function"] -],[ - "start", - ["text"," "], - ["keyword.control.elixir","def"], - ["text"," some_fun "], - ["keyword.control.elixir","do"] -],[ - "start", - ["text"," "], - ["variable.other.constant.elixir","IO"], - ["punctuation.separator.method.elixir","."], - ["text","puts "], - ["punctuation.definition.string.begin.elixir","\""], - ["string.quoted.double.elixir","Juhu Kinners!"], - ["punctuation.definition.string.end.elixir","\""] -],[ - "start", - ["text"," "], - ["keyword.control.elixir","end"] -],[ - "start", - ["text"," "], - ["punctuation.definition.comment.elixir","#"], - ["comment.line.number-sign.elixir"," A private function"] -],[ - "start", - ["text"," "], - ["keyword.control.elixir","defp"], - ["text"," priv "], - ["keyword.control.elixir","do"] -],[ - "punctuation.definition.string.begin.elixir7", - ["text"," is_regex "], - ["punctuation.definition.string.begin.elixir","~r\"\"\""] -],[ - "punctuation.definition.string.begin.elixir7", - ["string.quoted.double.heredoc.elixir"," This is a regex"] -],[ - "punctuation.definition.string.begin.elixir7", - ["string.quoted.double.heredoc.elixir"," spanning several"] -],[ - "punctuation.definition.string.begin.elixir7", - ["string.quoted.double.heredoc.elixir"," lines."] -],[ - "start", - ["punctuation.definition.string.end.elixir"," \"\"\""] -],[ - "start", - ["text"," x "], - ["keyword.operator.assignment.elixir","="], - ["text"," elem"], - ["punctuation.section.function.elixir","("], - ["punctuation.section.scope.elixir","{"], - ["text"," "], - ["punctuation.definition.constant.elixir",":"], - ["constant.other.symbol.elixir","a"], - ["punctuation.separator.object.elixir",","], - ["text"," "], - ["punctuation.definition.constant.elixir",":"], - ["constant.other.symbol.elixir","b"], - ["punctuation.separator.object.elixir",","], - ["text"," "], - ["punctuation.definition.constant.elixir",":"], - ["constant.other.symbol.elixir","c"], - ["text"," "], - ["punctuation.section.scope.elixir","}"], - ["punctuation.separator.object.elixir",","], - ["text"," "], - ["constant.numeric.elixir","0"], - ["punctuation.section.function.elixir",")"], - ["text"," "], - ["punctuation.definition.comment.elixir","#"], - ["comment.line.number-sign.elixir","=> :a"] -],[ - "start", - ["text"," "], - ["keyword.control.elixir","end"] -],[ - "start", - ["keyword.control.elixir","end"] -],[ - "start" -],[ - "start", - ["text","test_fun "], - ["keyword.operator.assignment.elixir","="], - ["text"," "], - ["keyword.control.elixir","fn"], - ["punctuation.section.function.elixir","("], - ["text","x"], - ["punctuation.section.function.elixir",")"], - ["text"," "], - ["keyword.operator.arithmetic.elixir","-"], - ["keyword.operator.comparison.elixir",">"] -],[ - "start", - ["text"," "], - ["keyword.control.elixir","cond"], - ["text"," "], - ["keyword.control.elixir","do"] -],[ - "start", - ["text"," x "], - ["keyword.operator.comparison.elixir",">"], - ["text"," "], - ["constant.numeric.elixir","10"], - ["text"," "], - ["keyword.operator.arithmetic.elixir","-"], - ["keyword.operator.comparison.elixir",">"] -],[ - "start", - ["text"," "], - ["punctuation.definition.constant.elixir",":"], - ["constant.other.symbol.elixir","greater_than_ten"] -],[ - "start", - ["text"," "], - ["constant.language.elixir","true"], - ["text"," "], - ["keyword.operator.arithmetic.elixir","-"], - ["keyword.operator.comparison.elixir",">"] -],[ - "start", - ["text"," "], - ["punctuation.definition.constant.elixir",":"], - ["constant.other.symbol.elixir","maybe_ten"] -],[ - "start", - ["text"," "], - ["keyword.control.elixir","end"] -],[ - "start", - ["keyword.control.elixir","end"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_elm.json b/lib/ace/mode/_test/tokens_elm.json deleted file mode 100644 index b39de92f..00000000 --- a/lib/ace/mode/_test/tokens_elm.json +++ /dev/null @@ -1,198 +0,0 @@ -[[ - "start", - ["comment.start","{-"], - ["comment"," Ace "], - ["comment.start","{-"], - ["comment"," 4 "], - ["comment.end","-}"], - ["comment"," Elm "], - ["comment.end","-}"] -],[ - "start", - ["constant.language","main"], - ["text"," "], - ["keyword","="], - ["text"," "], - ["identifier","lift"], - ["text"," "], - ["identifier","clock"], - ["text"," "], - ["paren.lparen","("], - ["identifier","every"], - ["text"," "], - ["identifier","second"], - ["paren.rparen",")"] -],[ - "start" -],[ - "start", - ["constant.language","clock"], - ["text"," "], - ["identifier","t"], - ["text"," "], - ["keyword","="], - ["text"," "], - ["identifier","collage"], - ["text"," "], - ["constant.numeric","400"], - ["text"," "], - ["constant.numeric","400"], - ["text"," "], - ["paren.lparen","["], - ["text"," "], - ["identifier","filled"], - ["text"," "], - ["identifier","lightGrey"], - ["text"," "], - ["paren.lparen","("], - ["identifier","ngon"], - ["text"," "], - ["constant.numeric","12"], - ["text"," "], - ["constant.numeric","110"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["operator.punctuation",","], - ["text"," "], - ["identifier","outlined"], - ["text"," "], - ["paren.lparen","("], - ["identifier","solid"], - ["text"," "], - ["identifier","grey"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","("], - ["identifier","ngon"], - ["text"," "], - ["constant.numeric","12"], - ["text"," "], - ["constant.numeric","110"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["operator.punctuation",","], - ["text"," "], - ["identifier","hand"], - ["text"," "], - ["identifier","orange"], - ["text"," "], - ["constant.numeric","100"], - ["text"," "], - ["identifier","t"] -],[ - "start", - ["text"," "], - ["operator.punctuation",","], - ["text"," "], - ["identifier","hand"], - ["text"," "], - ["identifier","charcoal"], - ["text"," "], - ["constant.numeric","100"], - ["text"," "], - ["paren.lparen","("], - ["identifier","t"], - ["keyword.operator","/"], - ["constant.numeric","60"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["operator.punctuation",","], - ["text"," "], - ["identifier","hand"], - ["text"," "], - ["identifier","charcoal"], - ["text"," "], - ["constant.numeric","60"], - ["text"," "], - ["paren.lparen","("], - ["identifier","t"], - ["keyword.operator","/"], - ["constant.numeric","720"], - ["paren.rparen",")"], - ["text"," "], - ["paren.rparen","]"] -],[ - "start" -],[ - "start", - ["constant.language","hand"], - ["text"," "], - ["identifier","clr"], - ["text"," "], - ["identifier","len"], - ["text"," "], - ["identifier","time"], - ["text"," "], - ["keyword","="] -],[ - "start", - ["text"," "], - ["keyword","let"], - ["text"," "], - ["identifier","angle"], - ["text"," "], - ["keyword","="], - ["text"," "], - ["identifier","degrees"], - ["text"," "], - ["paren.lparen","("], - ["constant.numeric","90"], - ["text"," "], - ["keyword.operator","-"], - ["text"," "], - ["constant.numeric","6"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["identifier","inSeconds"], - ["text"," "], - ["identifier","time"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["keyword","in"], - ["text"," "], - ["identifier","traced"], - ["text"," "], - ["paren.lparen","("], - ["identifier","solid"], - ["text"," "], - ["identifier","clr"], - ["paren.rparen",")"], - ["text"," "], - ["keyword.operator","<|"], - ["text"," "], - ["identifier","segment"], - ["text"," "], - ["paren.lparen","("], - ["constant.numeric","0"], - ["operator.punctuation",","], - ["constant.numeric","0"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","("], - ["identifier","len"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["identifier","cos"], - ["text"," "], - ["identifier","angle"], - ["operator.punctuation",","], - ["text"," "], - ["identifier","len"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["identifier","sin"], - ["text"," "], - ["identifier","angle"], - ["paren.rparen",")"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_ftl.json b/lib/ace/mode/_test/tokens_ftl.json index 75e7a6f1..eb81f1fb 100644 --- a/lib/ace/mode/_test/tokens_ftl.json +++ b/lib/ace/mode/_test/tokens_ftl.json @@ -43,110 +43,110 @@ "start" ],[ "start", - ["xml-pe.doctype.xml",""] + ["punctuation.doctype.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","lang"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"en-us\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","html"], + ["text"," "], + ["entity.other.attribute-name","lang"], + ["keyword.operator.separator","="], + ["string","\"en-us\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","head"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","head"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","meta"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","charset"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"utf-8\""], - ["text.tag-whitespace.xml"," "], - ["meta.tag.punctuation.tag-close.xml","/>"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","meta"], + ["text"," "], + ["entity.other.attribute-name","charset"], + ["keyword.operator.separator","="], + ["string","\"utf-8\""], + ["text"," "], + ["meta.tag.punctuation.end","/>"] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","title"], + ["meta.tag.punctuation.end",">"], ["string.interpolated","${"], ["variable","title"], ["keyword.operator","!"], ["string","\"FreeMarker\""], ["string.interpolated","}"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","title"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","body"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","body"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h1"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Hello "], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h1"], + ["meta.tag.punctuation.end",">"], + ["text","Hello "], ["string.interpolated","${"], ["variable","name"], ["keyword.operator","!"], ["string","\"\""], ["string.interpolated","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Today is: "], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text","Today is: "], ["string.interpolated","${"], ["language.variable",".now"], ["support.function","?date"], ["string.interpolated","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function","<#assign"], ["text"," "], ["variable","x"], @@ -157,7 +157,7 @@ ["keyword",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function","<#if"], ["text"," "], ["variable","x"], @@ -174,7 +174,7 @@ ["text"," "], ["constant.numeric","14"], ["keyword",">"], - ["text.xml","x equals 13: "], + ["text","x equals 13: "], ["string.interpolated","${"], ["variable","x"], ["string.interpolated","}"], @@ -182,16 +182,16 @@ ["keyword",">"] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","ul"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","ul"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function","<#list"], ["text"," "], ["variable","items"], @@ -202,14 +202,14 @@ ["keyword",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","li"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","li"], + ["meta.tag.punctuation.end",">"], ["string.interpolated","${"], ["variable","item_index"], ["string.interpolated","}"], - ["text.xml",": "], + ["text",": "], ["string.interpolated","${"], ["variable","item.name"], ["keyword.operator","!"], @@ -223,26 +223,26 @@ ["constant.numeric","0"], ["paren.rparen","]"], ["string.interpolated","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," User directive: "], + ["text"," User directive: "], ["keyword.other","<@lib.function"], ["text"," "], ["variable","attr1"], @@ -257,21 +257,21 @@ ["keyword.operator","="], ["constant.numeric","-42.12"], ["keyword",">"], - ["text.xml","Test"], + ["text","Test"], ["keyword.other",""] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.other","<@anotherOne"], ["text"," "], ["keyword","/>"] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function","<#if"], ["text"," "], ["variable","variable"], @@ -279,10 +279,10 @@ ["keyword",">"] ],[ "start", - ["text.xml"," Deprecated"] + ["text"," Deprecated"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function","<#elseif"], ["text"," "], ["variable","variable"], @@ -290,52 +290,52 @@ ["keyword",">"] ],[ "start", - ["text.xml"," Better"] + ["text"," Better"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function","<#else"], ["keyword",">"] ],[ "start", - ["text.xml"," Default"] + ["text"," Default"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["keyword.function",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.image.tag-name.xml","img"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","src"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"images/"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.image","img"], + ["text"," "], + ["entity.other.attribute-name","src"], + ["keyword.operator.separator","="], + ["string","\"images/"], ["string.interpolated","${"], ["variable","user.id"], ["string.interpolated","}"], - ["string.attribute-value.xml",".png\""], - ["text.tag-whitespace.xml"," "], - ["meta.tag.punctuation.tag-close.xml","/>"] + ["string",".png\""], + ["text"," "], + ["meta.tag.punctuation.end","/>"] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_gcode.json b/lib/ace/mode/_test/tokens_gcode.json deleted file mode 100644 index d6227473..00000000 --- a/lib/ace/mode/_test/tokens_gcode.json +++ /dev/null @@ -1,296 +0,0 @@ -[[ - "start", - ["identifier","O"], - ["constant.numeric","003"], - ["text"," "], - ["comment","(DIAMOND SQUARE)"] -],[ - "start", - ["comment","N2"], - ["text"," "], - ["string","G54"], - ["text"," "], - ["string","G90"], - ["text"," "], - ["string","G49"], - ["text"," "], - ["string","G80"] -],[ - "start", - ["comment","N3"], - ["text"," "], - ["string","M6"], - ["text"," "], - ["identifier","T"], - ["constant.numeric","1"], - ["text"," "], - ["comment","(1.ENDMILL)"] -],[ - "start", - ["comment","N4"], - ["text"," "], - ["string","M3"], - ["text"," "], - ["identifier","S"], - ["constant.numeric","1800"] -],[ - "start", - ["comment","N5"], - ["text"," "], - ["string","G0"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","-.6"], - ["text"," "], - ["identifier","Y"], - ["constant.numeric","2.050"] -],[ - "start", - ["comment","N6"], - ["text"," "], - ["string","G43"], - ["text"," "], - ["identifier","H"], - ["constant.numeric","1"], - ["text"," "], - ["identifier","Z"], - ["constant.numeric",".1"] -],[ - "start", - ["comment","N7"], - ["text"," "], - ["string","G1"], - ["text"," "], - ["identifier","Z"], - ["constant.numeric","-.3"], - ["text"," "], - ["identifier","F"], - ["constant.numeric","50."] -],[ - "start", - ["comment","N8"], - ["text"," "], - ["string","G41"], - ["text"," "], - ["identifier","D"], - ["constant.numeric","1"], - ["text"," "], - ["identifier","Y"], - ["constant.numeric","1.45"] -],[ - "start", - ["comment","N9"], - ["text"," "], - ["string","G1"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","0"], - ["text"," "], - ["identifier","F"], - ["constant.numeric","20."] -],[ - "start", - ["comment","N10"], - ["text"," "], - ["string","G2"], - ["text"," "], - ["identifier","J"], - ["constant.numeric","-1.45"] -],[ - "start", - ["comment","(CUTTER COMP CANCEL)"] -],[ - "start", - ["comment","N11"], - ["text"," "], - ["string","G1"], - ["text"," "], - ["identifier","Z"], - ["constant.numeric","-.2"], - ["text"," "], - ["identifier","F"], - ["constant.numeric","50."] -],[ - "start", - ["comment","N12"], - ["text"," "], - ["identifier","Y"], - ["constant.numeric","-.990"] -],[ - "start", - ["comment","N13"], - ["text"," "], - ["string","G40"] -],[ - "start", - ["comment","N14"], - ["text"," "], - ["string","G0"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","-.6"], - ["text"," "], - ["identifier","Y"], - ["constant.numeric","1.590"] -],[ - "start", - ["comment","N15"], - ["text"," "], - ["string","G0"], - ["text"," "], - ["identifier","Z"], - ["constant.numeric",".1"] -],[ - "start", - ["comment","N16"], - ["text"," "], - ["string","M5"], - ["text"," "], - ["string","G49"], - ["text"," "], - ["string","G28"], - ["text"," "], - ["string","G91"], - ["text"," "], - ["identifier","Z"], - ["constant.numeric","0"] -],[ - "start", - ["comment","N17"], - ["text"," "], - ["identifier","CALL"], - ["text"," "], - ["identifier","O"], - ["constant.numeric","9456"] -],[ - "start", - ["comment","N18"], - ["text"," #"], - ["constant.numeric","500"], - ["text","="], - ["constant.numeric","0.004"] -],[ - "start", - ["comment","N19"], - ["text"," #"], - ["constant.numeric","503"], - ["text","="], - ["paren.lparen","["], - ["text","#"], - ["constant.numeric","500"], - ["text","+#"], - ["constant.numeric","501"], - ["paren.rparen","]"] -],[ - "start", - ["comment","N20"], - ["text"," "], - ["identifier","VC"], - ["constant.numeric","45"], - ["text","="], - ["constant.numeric","0.0006"] -],[ - "start", - ["identifier","VS"], - ["constant.numeric","4"], - ["text","="], - ["constant.numeric","0.0007"] -],[ - "start", - ["comment","N21"], - ["text"," "], - ["string","G90"], - ["text"," "], - ["string","G10"], - ["text"," "], - ["identifier","L"], - ["constant.numeric","20"], - ["text"," "], - ["identifier","P"], - ["constant.numeric","3"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","5."], - ["identifier","Y"], - ["constant.numeric","4."], - ["text"," "], - ["identifier","Z"], - ["constant.numeric","6.567"] -],[ - "start", - ["comment","N22"], - ["text"," "], - ["string","G0"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","5000"] -],[ - "start", - ["comment","N23"], - ["text"," "], - ["identifier","IF"], - ["text"," "], - ["paren.lparen","["], - ["text","#"], - ["constant.numeric","1"], - ["text"," "], - ["identifier","LT"], - ["text"," "], - ["constant.numeric","0.370"], - ["paren.rparen","]"], - ["text"," "], - ["identifier","GOTO"], - ["text"," "], - ["constant.numeric","49"] -],[ - "start", - ["comment","N24"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","-0.678"], - ["text"," "], - ["identifier","Y"], - ["constant.numeric","+.990"] -],[ - "start", - ["comment","N25"], - ["text"," "], - ["string","G84.3"], - ["text"," "], - ["identifier","X"], - ["constant.numeric","-0.1"] -],[ - "start", - ["comment","N26"], - ["text"," #"], - ["constant.numeric","4"], - ["text","=#"], - ["constant.numeric","5"], - ["text","*"], - ["identifier","COS"], - ["paren.lparen","["], - ["constant.numeric","45"], - ["paren.rparen","]"] -],[ - "start", - ["comment","N27"], - ["text"," #"], - ["constant.numeric","4"], - ["text","=#"], - ["constant.numeric","5"], - ["text","*"], - ["identifier","SIN"], - ["paren.lparen","["], - ["constant.numeric","45"], - ["paren.rparen","]"] -],[ - "start", - ["comment","N28"], - ["text"," "], - ["identifier","VZOFZ"], - ["text","="], - ["constant.numeric","652.9658"] -],[ - "start", - ["text","%"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_gherkin.json b/lib/ace/mode/_test/tokens_gherkin.json deleted file mode 100644 index 173d9798..00000000 --- a/lib/ace/mode/_test/tokens_gherkin.json +++ /dev/null @@ -1,142 +0,0 @@ -[[ - "start", - ["comment","@these"], - ["text"," "], - ["comment","@are"], - ["text"," "], - ["comment","@tags"] -],[ - "start", - ["keyword","Feature:"], - ["text"," Serve coffee"] -],[ - "start", - ["text"," Coffee should not be served until paid for"] -],[ - "start", - ["text"," Coffee should not be served until the button has been pressed"] -],[ - "start", - ["text"," If there is no coffee left then money should be refunded"] -],[ - "start", - ["text"," "] -],[ - "start", - ["text"," "], - ["keyword","Scenario Outline:"], - ["text"," Eating"] -],[ - "start", - ["text"," "], - ["keyword","Given"], - ["text"," there are "], - ["comment",""], - ["text"," cucumbers"] -],[ - "start", - ["text"," "], - ["keyword","When"], - ["text"," I eat "], - ["comment",""], - ["text"," cucumbers"] -],[ - "start", - ["text"," "], - ["keyword","Then"], - ["text"," I should have "], - ["comment",""], - ["text"," cucumbers"] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword","Examples:"] -],[ - "start", - ["text"," "], - ["comment","|"], - ["string"," start "], - ["comment","|"], - ["string"," eat "], - ["comment","|"], - ["string"," left "], - ["comment","|"] -],[ - "start", - ["text"," "], - ["comment","|"], - ["string"," 12 "], - ["comment","|"], - ["string"," 5 "], - ["comment","|"], - ["string"," 7 "], - ["comment","|"] -],[ - "start", - ["text"," "], - ["comment","|"], - ["string"," 20 "], - ["comment","|"], - ["string"," 5 "], - ["comment","|"], - ["string"," 15 "], - ["comment","|"], - ["string"," "] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword","Scenario:"], - ["text"," Buy last coffee"] -],[ - "start", - ["text"," "], - ["keyword","Given"], - ["text"," there are "], - ["constant.numeric","1"], - ["text"," coffees left in the machine"] -],[ - "start", - ["text"," "], - ["keyword","And"], - ["text"," I have deposited "], - ["constant.numeric","1"], - ["text","$ "] -],[ - "start", - ["text"," "], - ["keyword","When"], - ["text"," I press the coffee button"] -],[ - "start", - ["text"," "], - ["keyword","Then"], - ["text"," I should be served a "], - ["string","\"coffee\""] -],[ - "start", - ["text"," "] -],[ - "start", - ["text"," "], - ["comment","# this a comment"] -],[ - "start", - ["text"," "] -],[ - "qqstring3", - ["text"," "], - ["string","\"\"\""] -],[ - "qqstring3", - ["string"," this is a "] -],[ - "qqstring3", - ["string"," pystring"] -],[ - "start", - ["string"," \"\"\""] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_gitignore.json b/lib/ace/mode/_test/tokens_gitignore.json deleted file mode 100644 index 8689a724..00000000 --- a/lib/ace/mode/_test/tokens_gitignore.json +++ /dev/null @@ -1,33 +0,0 @@ -[[ - "start", - ["comment","# A sample .gitignore file."] -],[ - "start" -],[ - "start", - ["text",".buildlog"] -],[ - "start", - ["text",".DS_Store"] -],[ - "start", - ["text",".svn"] -],[ - "start" -],[ - "start", - ["comment","# Negated patterns:"] -],[ - "start", - ["keyword","!foo.bar"] -],[ - "start" -],[ - "start", - ["comment","# Also ignore user settings..."] -],[ - "start", - ["text","/.settings"] -],[ - "start" -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_handlebars.json b/lib/ace/mode/_test/tokens_handlebars.json deleted file mode 100644 index 1ec79139..00000000 --- a/lib/ace/mode/_test/tokens_handlebars.json +++ /dev/null @@ -1,81 +0,0 @@ -[[ - "start", - ["comment.start","{{!--"], - ["comment"," Ace + :-}} "], - ["comment.end","--}}"] -],[ - "start" -],[ - "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"comments\""], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["text.xml"," "], - ["storage.type.start","{{#"], - ["variable.parameter","each"], - ["text"," "], - ["variable.parameter","comments"], - ["storage.type.end","}}"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"/posts/"], - ["storage.type.start","{{"], - ["text","../"], - ["variable.parameter","permalink"], - ["storage.type.end","}}"], - ["string.attribute-value.xml","#"], - ["storage.type.start","{{"], - ["variable.parameter","id"], - ["storage.type.end","}}"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["storage.type.start","{{"], - ["variable.parameter","title"], - ["storage.type.end","}}"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["support.function","{{{"], - ["variable.parameter","body"], - ["support.function","}}}"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["storage.type.start","{{/"], - ["variable.parameter","each"], - ["storage.type.end","}}"] -],[ - "start", - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start" -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_html.json b/lib/ace/mode/_test/tokens_html.json index c5f75eff..794ba26d 100644 --- a/lib/ace/mode/_test/tokens_html.json +++ b/lib/ace/mode/_test/tokens_html.json @@ -1,63 +1,51 @@ [[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","html"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","scripts"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.script.tag-name.xml","script"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","a"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","'a'"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["storage.type","var"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.script","script"], ["text"," "], - ["string","\""], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml","'123'"] + ["entity.other.attribute-name","a"], + ["keyword.operator.separator","="], + ["string","'a'"], + ["meta.tag.punctuation.end",">"], + ["storage.type","var"], + ["meta.tag.punctuation.begin",""], + ["text","'123'"] +],[ + ["qqstring_inner","start_tag_stuff"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\"abc"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["string"," def\""], + ["meta.tag.punctuation.end",">"] ],[ - ["string.attribute-value.xml0","tag_stuff"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"abc"] + ["qstring_inner","start_tag_stuff"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","'abc"] ],[ "start", - ["string.attribute-value.xml"," def\""], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - ["string.attribute-value.xml","tag_stuff"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","'abc"] -],[ - "start", - ["string.attribute-value.xml","def\\'"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["string","def\\'"], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_html_ruby.json b/lib/ace/mode/_test/tokens_html_ruby.json index 8ff5f6ea..619fb5dc 100644 --- a/lib/ace/mode/_test/tokens_html_ruby.json +++ b/lib/ace/mode/_test/tokens_html_ruby.json @@ -1,82 +1,82 @@ [[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h1"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Listing Books"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h1"], + ["meta.tag.punctuation.end",">"], + ["text","Listing Books"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","table"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","table"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","tr"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Title"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","th"], + ["meta.tag.punctuation.end",">"], + ["text","Title"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Summary"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","th"], + ["meta.tag.punctuation.end",">"], + ["text","Summary"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","th"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","th"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","th"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","th"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", ["support.ruby_tag","<%"], @@ -92,22 +92,22 @@ ["support.ruby_tag","%>"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","tr"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["comment.start.erb","<%#"], ["comment"," comment "], ["comment.end.erb","%>"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["meta.tag.punctuation.end",">"], ["support.ruby_tag","<%="], ["text"," "], ["identifier","book"], @@ -115,15 +115,15 @@ ["identifier","title"], ["text"," "], ["support.ruby_tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["meta.tag.punctuation.end",">"], ["support.ruby_tag","<%="], ["text"," "], ["identifier","book"], @@ -131,42 +131,38 @@ ["identifier","content"], ["text"," "], ["support.ruby_tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["meta.tag.punctuation.end",">"], ["support.ruby_tag","<%="], ["text"," "], ["support.function","link_to"], ["text"," "], - ["string.start","'"], - ["string","Show"], - ["string.end","'"], + ["string","'Show'"], ["text",", "], ["identifier","book"], ["text"," "], ["support.ruby_tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["meta.tag.punctuation.end",">"], ["support.ruby_tag","<%="], ["text"," "], ["support.function","link_to"], ["text"," "], - ["string.start","'"], - ["string","Edit"], - ["string.end","'"], + ["string","'Edit'"], ["text",", "], ["identifier","edit_book_path"], ["paren.lparen","("], @@ -174,22 +170,20 @@ ["paren.rparen",")"], ["text"," "], ["support.ruby_tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["meta.tag.punctuation.end",">"], ["support.ruby_tag","<%="], ["text"," "], ["support.function","link_to"], ["text"," "], - ["string.start","'"], - ["string","Remove"], - ["string.end","'"], + ["string","'Remove'"], ["text",", "], ["identifier","book"], ["text",", "], @@ -197,9 +191,7 @@ ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string.start","'"], - ["string","Are you sure?"], - ["string.end","'"], + ["string","'Are you sure?'"], ["text",", "], ["constant.other.symbol.ruby",":method"], ["text"," "], @@ -208,15 +200,15 @@ ["constant.other.symbol.ruby",":delete"], ["text"," "], ["support.ruby_tag","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", ["support.ruby_tag","<%"], @@ -226,30 +218,28 @@ ["support.ruby_tag","%>"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","br"], - ["text.tag-whitespace.xml"," "], - ["meta.tag.punctuation.tag-close.xml","/>"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","br"], + ["text"," "], + ["meta.tag.punctuation.end","/>"] ],[ "start", - ["text.xml"," "] + ["text"," "] ],[ "start", ["support.ruby_tag","<%="], ["text"," "], ["support.function","link_to"], ["text"," "], - ["string.start","'"], - ["string","New book"], - ["string.end","'"], + ["string","'New book'"], ["text",", "], ["identifier","new_book_path"], ["text"," "], diff --git a/lib/ace/mode/_test/tokens_ini.json b/lib/ace/mode/_test/tokens_ini.json deleted file mode 100644 index 11d28017..00000000 --- a/lib/ace/mode/_test/tokens_ini.json +++ /dev/null @@ -1,23 +0,0 @@ -[[ - "start", - ["punctuation.definition.entity.ini","["], - ["constant.section.group-title.ini",".ShellClassInfo"], - ["punctuation.definition.entity.ini","]"] -],[ - "start", - ["keyword.other.definition.ini","IconResource"], - ["punctuation.separator.key-value.ini","="], - ["text","..\\logo.png"] -],[ - "start", - ["punctuation.definition.entity.ini","["], - ["constant.section.group-title.ini","ViewState"], - ["punctuation.definition.entity.ini","]"] -],[ - "start", - ["keyword.other.definition.ini","FolderType"], - ["punctuation.separator.key-value.ini","="], - ["text","Generic"] -],[ - "start" -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_io.json b/lib/ace/mode/_test/tokens_io.json deleted file mode 100644 index b83a675a..00000000 --- a/lib/ace/mode/_test/tokens_io.json +++ /dev/null @@ -1,49 +0,0 @@ -[[ - "start", - ["punctuation.definition.comment.io","//"], - ["comment.line.double-slash.io"," computes factorial of a number"] -],[ - "start", - ["text","factorial "], - ["keyword.operator.io",":="], - ["text"," "], - ["support.function.io","method"], - ["text","(n,"] -],[ - "start", - ["text"," "], - ["keyword.control.io","if"], - ["text","(n "], - ["keyword.operator.io","=="], - ["text"," "], - ["constant.numeric.io","0"], - ["text",", "], - ["keyword.control.io","return"], - ["text"," "], - ["constant.numeric.io","1"], - ["text",")"] -],[ - "start", - ["text"," res "], - ["keyword.operator.io",":="], - ["text"," "], - ["constant.numeric.io","1"] -],[ - "start", - ["text"," "], - ["support.class.io","Range"], - ["text"," "], - ["constant.numeric.io","1"], - ["text"," "], - ["support.function.io","to"], - ["text","(n) "], - ["keyword.control.io","foreach"], - ["text","(i, res "], - ["keyword.operator.io","="], - ["text"," res "], - ["keyword.operator.io","*"], - ["text"," i)"] -],[ - "start", - ["text",")"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_jack.json b/lib/ace/mode/_test/tokens_jack.json deleted file mode 100644 index c3d694dd..00000000 --- a/lib/ace/mode/_test/tokens_jack.json +++ /dev/null @@ -1,1786 +0,0 @@ -[[ - "start", - ["keyword","vars"], - ["text"," "], - ["variable","it"], - ["text",", "], - ["variable","p"] -],[ - "start" -],[ - "start", - ["variable","p"], - ["text"," = "], - ["paren.lparen","{"], - ["variable","label"], - ["text",", "], - ["variable","value"], - ["text","|"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","\""], - ["constant.language.escape","\\n"], - ["string","\""], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","label"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["language.builtin","inspect"], - ["paren.lparen","("], - ["variable","value"], - ["paren.rparen","))"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start", - ["comment","-- Create an array from 0 to 15"] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"range\""], - ["text",", "], - ["language.builtin","i-collect"], - ["paren.lparen","("], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","5"], - ["paren.rparen",")))"] -],[ - "start" -],[ - "start", - ["comment","-- Create an array from 0 to 15 and break up in chunks of 4"] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"chunked range\""], - ["text",", "], - ["language.builtin","i-collect"], - ["paren.lparen","("], - ["language.builtin","i-chunk"], - ["paren.lparen","("], - ["constant.numeric","4"], - ["text",", "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","16"], - ["paren.rparen","))))"] -],[ - "start" -],[ - "start", - ["comment","-- Check if all or none items in stream pass test."] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"all < 60 in range(60)\""], - ["text",", "], - ["variable","i-all?"], - ["paren.lparen","({"], - ["variable","i"], - ["text","|"], - ["variable","i"], - ["keyword.operator","<"], - ["constant.numeric","60"], - ["paren.rparen","}"], - ["text",", "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","60"], - ["paren.rparen",")))"] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"any < 60 in range(60)\""], - ["text",", "], - ["variable","i-any?"], - ["paren.lparen","({"], - ["variable","i"], - ["text","|"], - ["variable","i"], - ["keyword.operator",">"], - ["constant.numeric","60"], - ["paren.rparen","}"], - ["text",", "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","60"], - ["paren.rparen",")))"] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"all < 60 in range(70)\""], - ["text",", "], - ["variable","i-all?"], - ["paren.lparen","({"], - ["variable","i"], - ["text","|"], - ["variable","i"], - ["keyword.operator","<"], - ["constant.numeric","60"], - ["paren.rparen","}"], - ["text",", "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","70"], - ["paren.rparen",")))"] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"any < 60 in range(70)\""], - ["text",", "], - ["variable","i-any?"], - ["paren.lparen","({"], - ["variable","i"], - ["text","|"], - ["variable","i"], - ["keyword.operator",">"], - ["constant.numeric","60"], - ["paren.rparen","}"], - ["text",", "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","70"], - ["paren.rparen",")))"] -],[ - "start" -],[ - "start", - ["comment","-- Zip three different collections together"] -],[ - "start", - ["variable","p"], - ["paren.lparen","("], - ["string","\"zipped\""], - ["text",", "], - ["language.builtin","i-collect"], - ["paren.lparen","("], - ["language.builtin","i-zip"], - ["paren.lparen","("] -],[ - "start", - ["text"," "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","10"], - ["paren.rparen",")"], - ["text",","] -],[ - "start", - ["text"," "], - ["paren.lparen","["], - ["constant.numeric","1"], - ["text",","], - ["constant.numeric","2"], - ["text",","], - ["constant.numeric","3"], - ["text",","], - ["constant.numeric","4"], - ["text",","], - ["constant.numeric","5"], - ["paren.rparen","]"], - ["text",","] -],[ - "start", - ["text"," "], - ["language.builtin","i-map"], - ["paren.lparen","({"], - ["variable","i"], - ["text","|"], - ["variable","i"], - ["keyword.operator","*"], - ["variable","i"], - ["paren.rparen","}"], - ["text",", "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","10"], - ["paren.rparen","))"] -],[ - "start", - ["paren.rparen",")))"] -],[ - "start" -],[ - "start", - ["keyword","vars"], - ["text"," "], - ["variable","names"], - ["text",", "], - ["variable","person"], - ["text",", "], - ["variable","i"], - ["text",", "], - ["variable","doubles"], - ["text",", "], - ["variable","lengths"], - ["text",", "], - ["variable","cubeRange"] -],[ - "start", - ["variable","names"], - ["text"," = "], - ["paren.lparen","["], - ["string","\"Thorin\""], - ["text",", "], - ["string","\"Dwalin\""], - ["text",", "], - ["string","\"Balin\""], - ["text",", "], - ["string","\"Bifur\""], - ["text",", "], - ["string","\"Bofur\""], - ["text",", "], - ["string","\"Bombur\""], - ["text",", "], - ["string","\"Oin\""], - ["text",","] -],[ - "start", - ["text"," "], - ["string","\"Gloin\""], - ["text",", "], - ["string","\"Ori\""], - ["text",", "], - ["string","\"Nori\""], - ["text",", "], - ["string","\"Dori\""], - ["text",", "], - ["string","\"Fili\""], - ["text",", "], - ["string","\"Kili\""], - ["text",", "], - ["string","\"Bilbo\""], - ["text",", "], - ["string","\"Gandalf\""], - ["paren.rparen","]"] -],[ - "start" -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["variable","names"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","!="], - ["text"," "], - ["string","\"Bilbo\""], - ["text"," "], - ["keyword.operator","&&"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","!="], - ["text"," "], - ["string","\"Gandalf\""], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["variable","person"], - ["text"," = "], - ["paren.lparen","{"], - ["variable","name"], - ["text",": "], - ["string","\"Tim\""], - ["text",", "], - ["variable","age"], - ["text",": "], - ["constant.numeric","30"], - ["paren.rparen","}"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","key"], - ["text",", "], - ["variable","value"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["variable","person"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","key"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\" = \""], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","value"], - ["paren.rparen",")"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["variable","i"], - ["text"," = "], - ["constant.numeric","0"] -],[ - "start", - ["keyword","while"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword.operator","<"], - ["text"," "], - ["constant.numeric","10"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","i"], - ["text"," = "], - ["variable","i"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","1"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","i"], - ["paren.rparen",")"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","("], - ["string","\"range\""], - ["paren.rparen",")"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","10"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","i"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","1"], - ["paren.rparen",")"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","10"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["constant.numeric","10"], - ["text"," "], - ["keyword.operator","-"], - ["text"," "], - ["variable","i"], - ["paren.rparen",")"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["comment","-- Dynamic object that gives the first 10 doubles"] -],[ - "start", - ["variable","doubles"], - ["text"," = "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["storage.form","@len"], - ["text",": "], - ["paren.lparen","{"], - ["text","| "], - ["constant.numeric","10"], - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["storage.form","@get"], - ["text",": "], - ["paren.lparen","{"], - ["variable","key"], - ["text","|"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","key"], - ["text"," "], - ["keyword","is"], - ["text"," "], - ["storage.type","Integer"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["variable","key"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["variable","key"], - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","("], - ["string","\"#doubles\""], - ["text",", "], - ["keyword.operator","#"], - ["variable","doubles"], - ["paren.rparen",")"] -],[ - "start" -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","("], - ["string","\"Doubles\""], - ["paren.rparen",")"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["variable","doubles"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","(["], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["paren.rparen","])"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["comment","-- Dynamic object that has names list as keys and string lenth as values"] -],[ - "start", - ["variable","lengths"], - ["text"," = "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["storage.form","@keys"], - ["text",": "], - ["paren.lparen","{"], - ["text","| "], - ["variable","names"], - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["storage.form","@get"], - ["text",": "], - ["paren.lparen","{"], - ["variable","key"], - ["text","|"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","key"], - ["text"," "], - ["keyword","is"], - ["text"," "], - ["storage.type","String"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["keyword.operator","#"], - ["variable","key"], - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["language.builtin","print"], - ["text"," "], - ["paren.lparen","("], - ["string","\"Lengths\""], - ["paren.rparen",")"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["variable","lengths"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","(["], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["paren.rparen","])"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start" -],[ - "start", - ["variable","cubeRange"], - ["text"," = "], - ["paren.lparen","{"], - ["variable","n"], - ["text","|"] -],[ - "start", - ["text"," "], - ["keyword","vars"], - ["text"," "], - ["variable","i"], - ["text",", "], - ["variable","v"] -],[ - "start", - ["text"," "], - ["variable","i"], - ["text"," = "], - ["constant.numeric","0"] -],[ - "start", - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["storage.form","@call"], - ["text",": "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["variable","v"], - ["text"," = "], - ["variable","i"] -],[ - "start", - ["text"," "], - ["variable","i"], - ["text"," = "], - ["variable","i"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","1"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","v"], - ["text"," "], - ["keyword.operator","<"], - ["text"," "], - ["variable","n"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["variable","v"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["variable","v"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["variable","v"], - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","("], - ["string","\"Cubes\""], - ["paren.rparen",")"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["variable","cubeRange"], - ["paren.lparen","("], - ["constant.numeric","5"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","(["], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["paren.rparen","])"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","("], - ["string","\"String\""], - ["paren.rparen",")"] -],[ - "start", - ["keyword","for"], - ["text"," "], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["string","\"Hello World\""], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","(["], - ["variable","k"], - ["text",", "], - ["variable","v"], - ["paren.rparen","])"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start" -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","(["], - ["variable","i"], - ["text"," "], - ["keyword","for"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","10"], - ["paren.rparen",")])"] -],[ - "start", - ["language.builtin","print"], - ["paren.lparen","(["], - ["variable","i"], - ["text"," "], - ["keyword","for"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","20"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword.operator","%"], - ["text"," "], - ["constant.numeric","3"], - ["paren.rparen","])"] -],[ - "start" -],[ - "start" -],[ - "start" -],[ - "start", - ["comment","-- Example showing how to do parallel work using split..and"] -],[ - "start", - ["variable","base"], - ["text"," = "], - ["paren.lparen","{"], - ["variable","bootstrap"], - ["text",", "], - ["variable","target-dir"], - ["text","|"] -],[ - "start", - ["text"," "], - ["keyword","split"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","copy"], - ["paren.lparen","("], - ["string","\"res\""], - ["text",", "], - ["variable","target-dir"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword","and"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","newer"], - ["paren.lparen","("], - ["string","\"src/*.less\""], - ["text",", "], - ["variable","target-dir"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\"/style.css\""], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","lessc"], - ["paren.lparen","("], - ["string","\"src/\""], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","bootstrap"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\".less\""], - ["text",", "], - ["variable","target-dir"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\"/style.css\""], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword","and"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","build"], - ["paren.lparen","("], - ["string","\"src/\""], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","bootstrap"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\".js\""], - ["text",", "], - ["variable","target-dir"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\"/app.js\""], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start" -],[ - "start", - ["keyword","vars"], - ["text"," "], - ["variable","Dragon"], - ["text",", "], - ["variable","pet"] -],[ - "start" -],[ - "start", - ["variable","Dragon"], - ["text"," = "], - ["paren.lparen","{"], - ["variable","name"], - ["text","|"] -],[ - "start", - ["text"," "], - ["keyword","vars"], - ["text"," "], - ["variable","asleep"], - ["text",", "], - ["variable","stuff-in-belly"], - ["text",", "], - ["variable","stuff-in-intestine"], - ["text",","] -],[ - "start", - ["text"," "], - ["variable","feed"], - ["text",", "], - ["variable","walk"], - ["text",", "], - ["variable","put-to-bed"], - ["text",", "], - ["variable","toss"], - ["text",", "], - ["variable","rock"], - ["text",","] -],[ - "start", - ["text"," "], - ["variable","hungry?"], - ["text",", "], - ["variable","poopy?"], - ["text",", "], - ["variable","passage-of-time"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","false"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-belly"], - ["text"," = "], - ["constant.numeric","10"], - ["text"," "], - ["comment","-- He's full."] -],[ - "start", - ["text"," "], - ["variable","stuff-in-intestine"], - ["text"," = "], - ["constant.numeric","0"], - ["text"," "], - ["comment","-- He doesn't need to go."] -],[ - "start" -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' is born.'"], - ["paren.rparen",")"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","feed"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'You feed '"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","'.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-belly"], - ["text"," = "], - ["constant.numeric","10"] -],[ - "start", - ["text"," "], - ["variable","passage-of-time"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","walk"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'You walk '"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\".\""], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-intestine"], - ["text"," = "], - ["constant.numeric","0"] -],[ - "start", - ["text"," "], - ["variable","passage-of-time"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","put-to-bed"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'You put '"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' to bed.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","true"] -],[ - "start", - ["text"," "], - ["keyword","for"], - ["text"," "], - ["variable","i"], - ["text"," "], - ["keyword","in"], - ["text"," "], - ["language.builtin","range"], - ["paren.lparen","("], - ["constant.numeric","3"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","passage-of-time"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' snores, filling the room with smoke.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","false"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' wakes up slowly.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","toss"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'You toss '"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' up into the air.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'He giggles, which singes your eyebrows.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["variable","passage-of-time"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","rock"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'You rock '"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' gently.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","true"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'He briefly dozes off...'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["variable","passage-of-time"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","false"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'...but wakes when you stop.'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","hungry?"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-belly"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["constant.numeric","2"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","poopy?"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-intestine"], - ["text"," "], - ["keyword.operator",">="], - ["text"," "], - ["constant.numeric","8"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["variable","passage-of-time"], - ["text"," = "], - ["paren.lparen","{"], - ["text","|"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","stuff-in-belly"], - ["text"," "], - ["keyword.operator",">"], - ["text"," "], - ["constant.numeric","0"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["comment","-- Move food from belly to intestine"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-belly"], - ["text"," = "], - ["variable","stuff-in-belly"], - ["text"," "], - ["keyword.operator","-"], - ["text"," "], - ["constant.numeric","1"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-intestine"], - ["text"," = "], - ["variable","stuff-in-intestine"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","1"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword","else"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["comment","-- Our dragon is starving!"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","false"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'He wakes up suddenly!'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' is starving! In desperation, he ate YOU!'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["keyword","abort"], - ["text"," "], - ["string","\"died\""] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","stuff-in-intestine"], - ["text"," "], - ["keyword.operator",">="], - ["text"," "], - ["constant.numeric","10"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","stuff-in-intestine"], - ["text"," = "], - ["constant.numeric","0"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'Whoops! '"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' had an accident...'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","hungry?"], - ["paren.lparen","("], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","false"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'He wakes up suddenly!'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","\"'s stomach grumbles...\""], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","poopy?"], - ["paren.lparen","("], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["variable","asleep"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","asleep"], - ["text"," = "], - ["constant.language.boolean","false"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["string","'He wakes up suddenly!'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["language.builtin","print"], - ["paren.lparen","("], - ["variable","name"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["string","' does the potty dance...'"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["text"," "], - ["comment","-- Export the public interface to this closure object."] -],[ - "start", - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text"," "], - ["variable","feed"], - ["text",": "], - ["variable","feed"] -],[ - "start", - ["text"," "], - ["variable","walk"], - ["text",": "], - ["variable","walk"] -],[ - "start", - ["text"," "], - ["variable","put-to-bed"], - ["text",": "], - ["variable","put-to-bed"] -],[ - "start", - ["text"," "], - ["variable","toss"], - ["text",": "], - ["variable","toss"] -],[ - "start", - ["text"," "], - ["variable","rock"], - ["text",": "], - ["variable","rock"] -],[ - "start", - ["text"," "], - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["variable","pet"], - ["text"," = "], - ["variable","Dragon"], - ["paren.lparen","("], - ["string","'Norbert'"], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","feed"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","toss"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","walk"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","put-to-bed"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","rock"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","put-to-bed"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","put-to-bed"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","put-to-bed"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start", - ["variable","pet"], - ["text","."], - ["variable","put-to-bed"], - ["paren.lparen","("], - ["paren.rparen",")"] -],[ - "start" -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_javascript.json b/lib/ace/mode/_test/tokens_javascript.json index 1be3f605..5044f21e 100644 --- a/lib/ace/mode/_test/tokens_javascript.json +++ b/lib/ace/mode/_test/tokens_javascript.json @@ -96,8 +96,7 @@ ["text"," "], ["string.regexp","/2 "], ["constant.language.escape","+"], - ["string.regexp"," 1/gimyx"], - ["identifier","k"] + ["string.regexp"," 1/b"] ],[ "no_regex", ["identifier","a"], @@ -288,9 +287,9 @@ ["string.regexp.charachterclass","r"], ["constant.language.escape","-"], ["string.regexp.charachterclass","o"], - ["regexp.charclass.keyword.operator","\\f\\f"], + ["regexp.keyword.operator","\\f\\f"], ["string.regexp.charachterclass","["], - ["regexp.charclass.keyword.operator","\\f"], + ["regexp.keyword.operator","\\f"], ["constant.language.escape","]?"], ["string.regexp","r"], ["invalid","{7}+"], @@ -379,7 +378,7 @@ ["constant.numeric","1."], ["text","00"], ["identifier","E"], - ["keyword.operator","^"], + ["text","^"], ["constant.numeric","1"], ["punctuation.operator",","], ["text"," "], diff --git a/lib/ace/mode/_test/tokens_jsoniq.json b/lib/ace/mode/_test/tokens_jsoniq.json deleted file mode 100644 index 0f4ee6e9..00000000 --- a/lib/ace/mode/_test/tokens_jsoniq.json +++ /dev/null @@ -1,4 +0,0 @@ -[[ - "[\"start\"]", - ["support.function","TODO"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_jsp.json b/lib/ace/mode/_test/tokens_jsp.json index 25d3af4d..cd556e46 100644 --- a/lib/ace/mode/_test/tokens_jsp.json +++ b/lib/ace/mode/_test/tokens_jsp.json @@ -1,19 +1,19 @@ [[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","html"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","body"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","body"], + ["meta.tag.punctuation.end",">"] ],[ "js-start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.script.tag-name.xml","script"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.script","script"], + ["meta.tag.punctuation.end",">"] ],[ "js-start", ["text"," "], @@ -40,15 +40,15 @@ ],[ "start", ["text"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "css-start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.style.tag-name.xml","style"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.style","style"], + ["meta.tag.punctuation.end",">"] ],[ ["css-ruleset","css-start"], ["text"," "], @@ -69,20 +69,20 @@ ],[ "start", ["text"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," Today's date: "], + ["text"," Today's date: "], ["meta.tag","<%"], ["keyword.operator","="], ["text"," "], @@ -103,13 +103,13 @@ ["meta.tag","%>"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag","<%"], ["keyword.operator","!"], ["text"," "], @@ -124,7 +124,7 @@ ["meta.tag","%>"] ],[ "jsp-start", - ["text.xml"," "], + ["text"," "], ["meta.tag",""] ],[ "jsp-start", @@ -145,11 +145,11 @@ "start" ],[ "start", - ["text.xml"," "], + ["text"," "], ["comment","<%-- This is JSP comment --%>"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag","<%@"], ["text"," "], ["identifier","directive"], @@ -163,161 +163,161 @@ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Select Languages:"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","Select Languages:"], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","form"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","ACTION"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"jspCheckBox.jsp\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","form"], + ["text"," "], + ["entity.other.attribute-name","ACTION"], + ["keyword.operator.separator","="], + ["string","\"jspCheckBox.jsp\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","input"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"checkbox\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","name"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"id\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","value"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"Java\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml"," Java"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","BR"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","input"], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"checkbox\""], + ["text"," "], + ["entity.other.attribute-name","name"], + ["keyword.operator.separator","="], + ["string","\"id\""], + ["text"," "], + ["entity.other.attribute-name","value"], + ["keyword.operator.separator","="], + ["string","\"Java\""], + ["meta.tag.punctuation.end",">"], + ["text"," Java"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","BR"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","input"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"checkbox\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","name"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"id\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","value"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\".NET\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml"," .NET"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","BR"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","input"], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"checkbox\""], + ["text"," "], + ["entity.other.attribute-name","name"], + ["keyword.operator.separator","="], + ["string","\"id\""], + ["text"," "], + ["entity.other.attribute-name","value"], + ["keyword.operator.separator","="], + ["string","\".NET\""], + ["meta.tag.punctuation.end",">"], + ["text"," .NET"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","BR"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","input"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"checkbox\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","name"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"id\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","value"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"PHP\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml"," PHP"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","BR"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","input"], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"checkbox\""], + ["text"," "], + ["entity.other.attribute-name","name"], + ["keyword.operator.separator","="], + ["string","\"id\""], + ["text"," "], + ["entity.other.attribute-name","value"], + ["keyword.operator.separator","="], + ["string","\"PHP\""], + ["meta.tag.punctuation.end",">"], + ["text"," PHP"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","BR"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","input"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"checkbox\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","name"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"id\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","value"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"C/C++\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml"," C/C++"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","BR"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","input"], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"checkbox\""], + ["text"," "], + ["entity.other.attribute-name","name"], + ["keyword.operator.separator","="], + ["string","\"id\""], + ["text"," "], + ["entity.other.attribute-name","value"], + ["keyword.operator.separator","="], + ["string","\"C/C++\""], + ["meta.tag.punctuation.end",">"], + ["text"," C/C++"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","BR"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","input"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"checkbox\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","name"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"id\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","value"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"PERL\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml"," PERL "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","BR"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","input"], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"checkbox\""], + ["text"," "], + ["entity.other.attribute-name","name"], + ["keyword.operator.separator","="], + ["string","\"id\""], + ["text"," "], + ["entity.other.attribute-name","value"], + ["keyword.operator.separator","="], + ["string","\"PERL\""], + ["meta.tag.punctuation.end",">"], + ["text"," PERL "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","BR"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.form.tag-name.xml","input"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"submit\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","value"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"Submit\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.form","input"], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"submit\""], + ["text"," "], + ["entity.other.attribute-name","value"], + ["keyword.operator.separator","="], + ["string","\"Submit\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "jsp-start", - ["text.xml"," "], + ["text"," "], ["meta.tag","<%"] ],[ "jsp-start", @@ -424,12 +424,12 @@ ["meta.tag","%>"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_julia.json b/lib/ace/mode/_test/tokens_julia.json index 5aaef6f9..f4ce4eab 100644 --- a/lib/ace/mode/_test/tokens_julia.json +++ b/lib/ace/mode/_test/tokens_julia.json @@ -38,13 +38,7 @@ ],[ "start" ],[ - "start", - ["text","v "], - ["keyword.operator.update.julia","="], - ["text"," "], - ["variable","α"], - ["keyword.operator.transposed-variable.julia","'"], - ["text",";"] + "start" ],[ "start", ["keyword.other.julia","function"], diff --git a/lib/ace/mode/_test/tokens_latex.json b/lib/ace/mode/_test/tokens_latex.json index 52508e0d..0ac37725 100644 --- a/lib/ace/mode/_test/tokens_latex.json +++ b/lib/ace/mode/_test/tokens_latex.json @@ -2,37 +2,37 @@ "start", ["keyword","\\usepackage"], ["lparen","{"], - ["storage.type","amsmath"], + ["text","amsmath"], ["rparen","}"] ],[ "start", - ["storage.type","\\title"], + ["keyword","\\title"], ["lparen","{"], - ["storage.type","\\LaTeX"], + ["keyword","\\LaTeX"], ["rparen","}"] ],[ "start", - ["storage.type","\\date"], + ["keyword","\\date"], ["lparen","{"], ["rparen","}"] ],[ "start", - ["storage.type","\\begin"], + ["keyword","\\begin"], ["lparen","{"], - ["variable.parameter","document"], + ["text","document"], ["rparen","}"] ],[ "start", ["text"," "], - ["storage.type","\\maketitle"] + ["keyword","\\maketitle"] ],[ "start", ["text"," "], - ["storage.type","\\LaTeX"], + ["keyword","\\LaTeX"], ["lparen","{"], ["rparen","}"], ["text"," is a document preparation system for the "], - ["storage.type","\\TeX"], + ["keyword","\\TeX"], ["lparen","{"], ["rparen","}"] ],[ @@ -50,26 +50,26 @@ ],[ "start", ["text"," and much more. "], - ["storage.type","\\LaTeX"], + ["keyword","\\LaTeX"], ["lparen","{"], ["rparen","}"], ["text"," was originally written in 1984 by Leslie"] ],[ "start", ["text"," Lamport and has become the dominant method for using "], - ["storage.type","\\TeX"], + ["keyword","\\TeX"], ["text","; few"] ],[ "start", ["text"," people write in plain "], - ["storage.type","\\TeX"], + ["keyword","\\TeX"], ["lparen","{"], ["rparen","}"], ["text"," anymore. The current version is"] ],[ "start", ["text"," "], - ["storage.type","\\LaTeXe"], + ["keyword","\\LaTeXe"], ["text","."] ],[ "start", @@ -85,26 +85,26 @@ ],[ "start", ["text"," "], - ["storage.type","\\begin"], + ["keyword","\\begin"], ["lparen","{"], - ["variable.parameter","align"], + ["text","align"], ["rparen","}"] ],[ "start", ["text"," E &= mc^2 "], - ["constant.character.escape","\\\\"] + ["keyword","\\\\"] ],[ "start", ["text"," m &= "], - ["storage.type","\\frac"], + ["keyword","\\frac"], ["lparen","{"], ["text","m_0"], ["rparen","}"], ["lparen","{"], - ["storage.type","\\sqrt"], + ["keyword","\\sqrt"], ["lparen","{"], ["text","1-"], - ["storage.type","\\frac"], + ["keyword","\\frac"], ["lparen","{"], ["text","v^2"], ["rparen","}"], @@ -114,14 +114,14 @@ ],[ "start", ["text"," "], - ["storage.type","\\end"], + ["keyword","\\end"], ["lparen","{"], - ["variable.parameter","align"], + ["text","align"], ["rparen","}"] ],[ "start", - ["storage.type","\\end"], + ["keyword","\\end"], ["lparen","{"], - ["variable.parameter","document"], + ["text","document"], ["rparen","}"] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_liquid.json b/lib/ace/mode/_test/tokens_liquid.json index 30d003cb..a87c051d 100644 --- a/lib/ace/mode/_test/tokens_liquid.json +++ b/lib/ace/mode/_test/tokens_liquid.json @@ -1,56 +1,56 @@ [[ "start", - ["text.xml","The following examples can be found in full at http://liquidmarkup.org/"] + ["text","The following examples can be found in full at http://liquidmarkup.org/"] ],[ "start" ],[ "start", - ["text.xml","Liquid is an extraction from the e-commerce system Shopify."] + ["text","Liquid is an extraction from the e-commerce system Shopify."] ],[ "start", - ["text.xml","Shopify powers many thousands of e-commerce stores which all call for unique designs."] + ["text","Shopify powers many thousands of e-commerce stores which all call for unique designs."] ],[ "start", - ["text.xml","For this we developed Liquid which allows our customers complete design freedom while"] + ["text","For this we developed Liquid which allows our customers complete design freedom while"] ],[ "start", - ["text.xml","maintaining the integrity of our servers."] + ["text","maintaining the integrity of our servers."] ],[ "start" ],[ "start", - ["text.xml","Liquid has been in production use since June 2006 and is now used by many other"] + ["text","Liquid has been in production use since June 2006 and is now used by many other"] ],[ "start", - ["text.xml","hosted web applications."] + ["text","hosted web applications."] ],[ "start" ],[ "start", - ["text.xml","It was developed for usage in Ruby on Rails web applications and integrates seamlessly"] + ["text","It was developed for usage in Ruby on Rails web applications and integrates seamlessly"] ],[ "start", - ["text.xml","as a plugin but it also works excellently as a stand alone library."] + ["text","as a plugin but it also works excellently as a stand alone library."] ],[ "start" ],[ "start", - ["text.xml","Here's what it looks like:"] + ["text","Here's what it looks like:"] ],[ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","ul"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"products\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","ul"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"products\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","for"], @@ -64,16 +64,16 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","li"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","li"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], ["variable","{{"], ["text"," "], ["identifier","product"], @@ -81,12 +81,12 @@ ["identifier","title"], ["text"," "], ["variable","}}"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," Only "], + ["text"," Only "], ["variable","{{"], ["text"," "], ["identifier","product"], @@ -100,10 +100,10 @@ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], ["variable","{{"], ["text"," "], ["identifier","product"], @@ -117,20 +117,20 @@ ["constant.numeric","200"], ["text"," "], ["variable","}}"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","endfor"], @@ -138,34 +138,34 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start" ],[ "start", - ["text.xml","Some more features include:"] + ["text","Some more features include:"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Filters"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","Filters"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml"," The word \"tobi\" in uppercase: "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text"," The word \"tobi\" in uppercase: "], ["variable","{{"], ["text"," "], ["string","'tobi'"], @@ -173,16 +173,16 @@ ["support.function","upcase"], ["text"," "], ["variable","}}"], - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","The word \"tobi\" has "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text","The word \"tobi\" has "], ["variable","{{"], ["text"," "], ["string","'tobi'"], @@ -190,16 +190,16 @@ ["support.function","size"], ["text"," "], ["variable","}}"], - ["text.xml"," letters! "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," letters! "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Change \"Hello world\" to \"Hi world\": "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text","Change \"Hello world\" to \"Hi world\": "], ["variable","{{"], ["text"," "], ["string","'Hello world'"], @@ -211,16 +211,16 @@ ["string","'Hi'"], ["text"," "], ["variable","}}"], - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","The date today is "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text","The date today is "], ["variable","{{"], ["text"," "], ["string","'now'"], @@ -230,31 +230,31 @@ ["string","\"%Y %b %d\""], ["text"," "], ["variable","}}"], - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","If"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","If"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","if"], @@ -278,13 +278,13 @@ ["string","'marc'"], ["text"," "], ["variable","%}"], - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," hi marc or tobi"] + ["text"," hi marc or tobi"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","endif"], @@ -292,30 +292,30 @@ ["variable","%}"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Case"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","Case"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","case"], @@ -325,7 +325,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","when"], @@ -335,10 +335,10 @@ ["variable","%}"] ],[ "start", - ["text.xml"," Welcome"] + ["text"," Welcome"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","when"], @@ -348,7 +348,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{{"], ["text"," "], ["identifier","product"], @@ -358,7 +358,7 @@ ["identifier","link_to_vendor"], ["text"," "], ["variable","}}"], - ["text.xml"," / "], + ["text"," / "], ["variable","{{"], ["text"," "], ["identifier","product"], @@ -368,7 +368,7 @@ ["variable","}}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","else"], @@ -376,7 +376,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{{"], ["text"," "], ["identifier","page_title"], @@ -384,7 +384,7 @@ ["variable","}}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","endcase"], @@ -392,30 +392,30 @@ ["variable","%}"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","For Loops"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","For Loops"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","for"], @@ -427,10 +427,10 @@ ["identifier","array"], ["text"," "], ["variable","%}"], - ["text.xml"," "] + ["text"," "] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{{"], ["text"," "], ["identifier","item"], @@ -438,7 +438,7 @@ ["variable","}}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","endfor"], @@ -446,30 +446,30 @@ ["variable","%}"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Tables"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","Tables"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","tablerow"], @@ -487,7 +487,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","if"], @@ -499,7 +499,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," First column: "], + ["text"," First column: "], ["variable","{{"], ["text"," "], ["identifier","item"], @@ -509,7 +509,7 @@ ["variable","}}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","else"], @@ -517,7 +517,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," Different column: "], + ["text"," Different column: "], ["variable","{{"], ["text"," "], ["identifier","item"], @@ -527,7 +527,7 @@ ["variable","}}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","endif"], @@ -535,7 +535,7 @@ ["variable","%}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable","{%"], ["text"," "], ["keyword","endtablerow"], @@ -543,9 +543,9 @@ ["variable","%}"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_lsl.json b/lib/ace/mode/_test/tokens_lsl.json index 2248a607..83b7352b 100644 --- a/lib/ace/mode/_test/tokens_lsl.json +++ b/lib/ace/mode/_test/tokens_lsl.json @@ -1,6 +1,6 @@ [[ "comment", - ["comment.block.begin.lsl","/*"] + ["comment.block.lsl","/*"] ],[ "comment", ["comment.block.lsl"," Testing syntax highlighting"] @@ -12,7 +12,7 @@ ["comment.block.lsl"," for the Linden Scripting Language"] ],[ "start", - ["comment.block.end.lsl","*/"] + ["comment.block.lsl","*/"] ],[ "start" ],[ @@ -51,14 +51,14 @@ "start", ["storage.type.lsl","integer"], ["text.lsl"," "], - ["invalid.illegal.lsl","event"], + ["invalid.unimplemented.lsl","event"], ["text.lsl"," "], ["keyword.operator.lsl","="], ["text.lsl"," "], ["constant.numeric.lsl","5673"], ["punctuation.operator.lsl",";"], ["text.lsl"," "], - ["comment.line.double-slash.lsl","// invalid.illegal"] + ["comment.line.double-slash.lsl","// unimplemented reserved keyword!"] ],[ "start" ],[ @@ -368,14 +368,14 @@ ],[ "start", ["text.lsl"," "], - ["invalid.illegal.lsl","event"], + ["invalid.unimplemented.lsl","event"], ["text.lsl"," "], ["keyword.operator.lsl","="], ["text.lsl"," "], ["constant.numeric.lsl","5673"], ["punctuation.operator.lsl",";"], ["text.lsl"," "], - ["comment.line.double-slash.lsl","// invalid.illegal"] + ["comment.line.double-slash.lsl","// unimplemented reserved keyword!"] ],[ "start" ],[ @@ -401,21 +401,13 @@ ],[ "start", ["text.lsl"," "], - ["reserved.godmode.lsl","llSetInventoryPermMask"], + ["invalid.deprecated.lsl","llCloud"], ["paren.lparen.lsl","("], - ["string.quoted.double.lsl.start","\""], - ["string.quoted.double.lsl","some item"], - ["string.quoted.double.lsl.end","\""], - ["punctuation.operator.lsl",","], - ["text.lsl"," "], - ["constant.language.integer.lsl","MASK_NEXT"], - ["punctuation.operator.lsl",","], - ["text.lsl"," "], - ["constant.language.integer.lsl","PERM_ALL"], + ["constant.language.vector.lsl","ZERO_VECTOR"], ["paren.rparen.lsl",")"], ["punctuation.operator.lsl",";"], - ["text.lsl"," "], - ["comment.line.double-slash.lsl","// reserved.godmode"] + ["text.lsl"," "], + ["comment.line.double-slash.lsl","// invalid deprecated function!"] ],[ "start" ],[ @@ -428,9 +420,9 @@ ["text.lsl"," "], ["string.quoted.double.lsl.start","\""], ["string.quoted.double.lsl","Leaving "], - ["constant.character.escape.lsl","\\\""], + ["constant.language.escape.lsl","\\\""], ["string.quoted.double.lsl","default"], - ["constant.character.escape.lsl","\\\""], + ["constant.language.escape.lsl","\\\""], ["string.quoted.double.lsl"," now..."], ["string.quoted.double.lsl.end","\""], ["paren.rparen.lsl",")"], @@ -475,13 +467,13 @@ ["text.lsl"," "], ["string.quoted.double.lsl.start","\""], ["string.quoted.double.lsl","Entered "], - ["constant.character.escape.lsl","\\\""], + ["constant.language.escape.lsl","\\\""], ["string.quoted.double.lsl","state other"], - ["constant.character.escape.lsl","\\\""], + ["constant.language.escape.lsl","\\\""], ["string.quoted.double.lsl",", returning to "], - ["constant.character.escape.lsl","\\\""], + ["constant.language.escape.lsl","\\\""], ["string.quoted.double.lsl","default"], - ["constant.character.escape.lsl","\\\""], + ["constant.language.escape.lsl","\\\""], ["string.quoted.double.lsl"," again..."], ["string.quoted.double.lsl.end","\""], ["paren.rparen.lsl",")"], diff --git a/lib/ace/mode/_test/tokens_lua.json b/lib/ace/mode/_test/tokens_lua.json index b60c7cb1..276b3ffc 100644 --- a/lib/ace/mode/_test/tokens_lua.json +++ b/lib/ace/mode/_test/tokens_lua.json @@ -201,7 +201,7 @@ ["keyword.operator","="], ["keyword","function"], ["paren.lparen","("], - ["variable.language","self"], + ["identifier","self"], ["text",", "], ["identifier","other"], ["paren.rparen",")"] @@ -266,7 +266,7 @@ ["text"," "], ["keyword","return"], ["text"," "], - ["variable.language","self"], + ["identifier","self"], ["keyword.operator",":"], ["support.function","format"], ["paren.lparen","("], diff --git a/lib/ace/mode/_test/tokens_luapage.json b/lib/ace/mode/_test/tokens_luapage.json index 1fa765dd..3cee0815 100644 --- a/lib/ace/mode/_test/tokens_luapage.json +++ b/lib/ace/mode/_test/tokens_luapage.json @@ -1,24 +1,24 @@ [[ "doctype", - ["text.xml",""], - ["xml-pe.doctype.xml",""] + ["text"," "], + ["string","\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\""], + ["punctuation.doctype.end",">"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","html"], + ["meta.tag.punctuation.end",">"] ],[ ["lua-bracketedComment",2,"lua-start"], ["keyword","<%"], @@ -37,32 +37,32 @@ ["keyword","%>"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","head"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","head"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Reference"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","title"], + ["meta.tag.punctuation.end",">"], + ["text","Reference"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","link"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","rel"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"stylesheet\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","link"], + ["text"," "], + ["entity.other.attribute-name","rel"], + ["keyword.operator.separator","="], + ["string","\"stylesheet\""], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\""], ["keyword","<%="], ["identifier","luadoc"], ["text","."], @@ -75,129 +75,129 @@ ["string","\"luadoc.css\""], ["paren.rparen",")"], ["keyword","%>"], - ["string.attribute-value.xml","\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"text/css\""], - ["text.tag-whitespace.xml"," "], - ["meta.tag.punctuation.tag-close.xml","/>"] + ["string","\""], + ["text"," "], + ["entity.other.attribute-name","type"], + ["keyword.operator.separator","="], + ["string","\"text/css\""], + ["text"," "], + ["meta.tag.punctuation.end","/>"] ],[ "start", - ["text.xml","\t"], - ["comment.xml",""] + ["text","\t"], + ["comment",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","body"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","body"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"container\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"container\""], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"product\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"product\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"product_logo\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"product_logo\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"product_name\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","big"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","b"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"product_name\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","big"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","b"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""], + ["meta.tag.punctuation.begin",""], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"product_description\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"product_description\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," "], - ["comment.xml",""] + ["meta.tag.punctuation.begin",""], + ["text"," "], + ["comment",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"main\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"main\""], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"navigation\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"navigation\""], + ["meta.tag.punctuation.end",">"] ],[ "start", ["keyword","<%="], @@ -223,22 +223,22 @@ "start" ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," "], - ["comment.xml",""] + ["meta.tag.punctuation.begin",""], + ["text"," "], + ["comment",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"content\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"content\""], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ @@ -267,25 +267,25 @@ ["keyword","then%>"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Modules"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","Modules"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","table"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"module_list\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","table"], + ["text"," "], + ["entity.other.attribute-name","class"], + ["keyword.operator.separator","="], + ["string","\"module_list\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["comment.xml",""] + ["comment",""] ],[ "start", ["keyword","<%for"], @@ -306,26 +306,26 @@ ["keyword","do%>"] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text","\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","tr"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml","\t\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"name\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], + ["text","\t\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["text"," "], + ["entity.other.attribute-name","class"], + ["keyword.operator.separator","="], + ["string","\"name\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\""], ["keyword","<%="], ["identifier","luadoc"], ["text","."], @@ -340,27 +340,27 @@ ["identifier","doc"], ["paren.rparen",")"], ["keyword","%>"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], + ["string","\""], + ["meta.tag.punctuation.end",">"], ["keyword","<%="], ["identifier","modulename"], ["keyword","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","\t\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"summary\""], - ["meta.tag.punctuation.tag-close.xml",">"], + ["text","\t\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["text"," "], + ["entity.other.attribute-name","class"], + ["keyword.operator.separator","="], + ["string","\"summary\""], + ["meta.tag.punctuation.end",">"], ["keyword","<%="], ["identifier","doc"], ["text","."], @@ -371,23 +371,23 @@ ["text","."], ["identifier","summary"], ["keyword","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t"], + ["meta.tag.punctuation.begin",""] ],[ "start", ["keyword","<%end%>"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", ["keyword","<%end%>"] @@ -421,25 +421,25 @@ ["keyword","then%>"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h2"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Files"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h2"], + ["meta.tag.punctuation.end",">"], + ["text","Files"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","table"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"file_list\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","table"], + ["text"," "], + ["entity.other.attribute-name","class"], + ["keyword.operator.separator","="], + ["string","\"file_list\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["comment.xml",""] + ["comment",""] ],[ "start", ["keyword","<%for"], @@ -460,26 +460,26 @@ ["keyword","do%>"] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","tr"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text","\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","tr"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml","\t\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"name\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], + ["text","\t\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["text"," "], + ["entity.other.attribute-name","class"], + ["keyword.operator.separator","="], + ["string","\"name\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\""], ["keyword","<%="], ["identifier","luadoc"], ["text","."], @@ -492,44 +492,44 @@ ["identifier","filepath"], ["paren.rparen",")"], ["keyword","%>"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], + ["string","\""], + ["meta.tag.punctuation.end",">"], ["keyword","<%="], ["identifier","filepath"], ["keyword","%>"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","\t\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.table.tag-name.xml","td"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","class"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"summary\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.table","td"], + ["text"," "], + ["entity.other.attribute-name","class"], + ["keyword.operator.separator","="], + ["string","\"summary\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t"], + ["meta.tag.punctuation.begin",""] ],[ "start", ["keyword","<%end%>"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", ["keyword","<%end%>"] @@ -537,97 +537,97 @@ "start" ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," "], - ["comment.xml",""] + ["meta.tag.punctuation.begin",""], + ["text"," "], + ["comment",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," "], - ["comment.xml",""] + ["meta.tag.punctuation.begin",""], + ["text"," "], + ["comment",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","div"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"about\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","div"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"about\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml","\t"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"http://validator.w3.org/check?uri=referer\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.image.tag-name.xml","img"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","src"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"http://www.w3.org/Icons/valid-xhtml10\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","alt"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"Valid XHTML 1.0!\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","height"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"31\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","width"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"88\""], - ["text.tag-whitespace.xml"," "], - ["meta.tag.punctuation.tag-close.xml","/>"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text","\t"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\"http://validator.w3.org/check?uri=referer\""], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.image","img"], + ["text"," "], + ["entity.other.attribute-name","src"], + ["keyword.operator.separator","="], + ["string","\"http://www.w3.org/Icons/valid-xhtml10\""], + ["text"," "], + ["entity.other.attribute-name","alt"], + ["keyword.operator.separator","="], + ["string","\"Valid XHTML 1.0!\""], + ["text"," "], + ["entity.other.attribute-name","height"], + ["keyword.operator.separator","="], + ["string","\"31\""], + ["text"," "], + ["entity.other.attribute-name","width"], + ["keyword.operator.separator","="], + ["string","\"88\""], + ["text"," "], + ["meta.tag.punctuation.end","/>"], + ["meta.tag.punctuation.begin",""], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," "], - ["comment.xml",""] + ["meta.tag.punctuation.begin",""], + ["text"," "], + ["comment",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," "], - ["comment.xml",""], - ["text.xml","\t"] + ["meta.tag.punctuation.begin",""], + ["text"," "], + ["comment",""], + ["text","\t"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_markdown.json b/lib/ace/mode/_test/tokens_markdown.json index 29e878b2..3c0db62f 100644 --- a/lib/ace/mode/_test/tokens_markdown.json +++ b/lib/ace/mode/_test/tokens_markdown.json @@ -1,49 +1,49 @@ [[ "start", - ["text.xml","test: header 1 "] + ["text","test: header 1 "] ],[ "start", ["markup.heading.1","#"], ["heading","f"] ],[ "start", - ["text.xml","test: header 2"] + ["text","test: header 2"] ],[ "start", ["markup.heading.2","##"], ["heading"," foo"] ],[ "start", - ["text.xml","test: header ends with ' #'"] + ["text","test: header ends with ' #'"] ],[ "start", ["markup.heading.1","#"], ["heading"," # # "] ],[ "start", - ["text.xml","test: header ends with '#'"] + ["text","test: header ends with '#'"] ],[ "start", ["markup.heading.1","#"], ["heading","foo# "] ],[ "start", - ["text.xml","test: 6+ #s is not a valid header"] + ["text","test: 6+ #s is not a valid header"] ],[ "start", - ["text.xml","####### foo"] + ["text","####### foo"] ],[ "start", - ["text.xml","test: # followed be only space is not a valid header"] + ["text","test: # followed be only space is not a valid header"] ],[ "start", - ["text.xml","# "] + ["text","# "] ],[ "start", - ["text.xml","test: only space between #s is not a valid header"] + ["text","test: only space between #s is not a valid header"] ],[ "start", - ["text.xml","# #"] + ["text","# #"] ],[ "allowBlock" ],[ @@ -88,9 +88,9 @@ "listblock", ["markup.list","* "], ["list","usually "], - ["string.emphasis","*work*"], + ["string","*work*"], ["list"," fine ("], - ["string.emphasis","_em_"], + ["string","_em_"], ["list",")"] ],[ "listblock", @@ -99,14 +99,14 @@ "start" ],[ "start", - ["text.xml","in plain text "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","b"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","http://ace.ajaxorg.com"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","b"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text","in plain text "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","b"], + ["meta.tag.punctuation.end",">"], + ["text","http://ace.ajaxorg.com"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","b"], + ["meta.tag.punctuation.end",">"] ],[ "allowBlock" ],[ diff --git a/lib/ace/mode/_test/tokens_mask.json b/lib/ace/mode/_test/tokens_mask.json deleted file mode 100644 index 5f2b9762..00000000 --- a/lib/ace/mode/_test/tokens_mask.json +++ /dev/null @@ -1,302 +0,0 @@ -[[ - "start", - ["comment","/* Mask Syntax Demo */"] -],[ - "start" -],[ - "start", - ["keyword.support.constant.language","div"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["string.start","'"], - ["string"," Test "], - ["paren.lparen.markup.italic","~["], - ["identifier","name"], - ["paren.rparen.markup.italic","]"], - ["string.end","'"], - ["paren.rparen",";"] -],[ - "start" -],[ - "start", - ["keyword","define"], - ["text"," :"], - ["support.variable.class","userProfile"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text","\t"], - ["keyword.support.constant.language","header"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text","\t\t"], - ["keyword.support.constant.language","h4"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["support.function.markup.bold","@title"], - ["paren.lparen",";"] -],[ - "start", - ["text","\t\t"], - ["keyword.support.constant.language","button"], - ["support.variable.class",".close"], - ["paren.lparen",";"] -],[ - "start", - ["text","\t"], - ["paren.rparen","}"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - "start", - ["support.function.markup.bold",":userProfile"], - ["text"," "], - ["paren.lparen","{"] -],[ - "start", - ["text","\t"], - ["support.function.markup.bold","@title"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["string.start","'"], - ["string"," Hello "], - ["paren.lparen.markup.italic","~["], - ["keyword.control.markup.italic",":"], - ["text"," "], - ["identifier","username"], - ["punctuation.operator","."], - ["support.function","toUpperCase"], - ["paren.lparen","("], - ["paren.rparen",")"], - ["paren.rparen.markup.italic","]"], - ["string.end","'"] -],[ - "start", - ["paren.rparen","}"] -],[ - "start" -],[ - ["paren.lparen52","constant.language40"], - ["constant.language","style"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["css-block-ruleset","paren.lparen52","paren.lparen52","constant.language40"], - ["text"," "], - ["constant","html"], - ["text",", "], - ["constant","body"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["css-block-ruleset","paren.lparen52","paren.lparen52","constant.language40"], - ["text"," "], - ["support.type","background"], - ["text",": "], - ["support.function","url("], - ["string","'name.png'"], - ["support.function",")"], - ["text"," "], - ["constant.numeric","0"], - ["text"," "], - ["constant.numeric","0"], - ["text"," "], - ["support.constant","no-repeat"], - ["text",";"] -],[ - ["paren.lparen52","constant.language40"], - ["text"," "], - ["paren.rparen","}"] -],[ - ["#tmp","css-block-end","paren.lparen52","constant.language40"], - ["paren.rparen","}"] -],[ - ["#tmp","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","start","paren.lparen52","constant.language40"], - ["keyword.support.constant.language","button"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["text","\t"], - ["constant.language","event"], - ["text"," "], - ["support.variable.class","click"], - ["text"," "], - ["paren.lparen","("], - ["identifier","e"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["#tmp","js-block-start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["text","\t "], - ["variable.language","this"], - ["punctuation.operator","."], - ["identifier","textContent"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["string.quasi.start","`"], - ["string.quasi","name "], - ["paren.quasi.start","${"], - ["identifier","e"], - ["punctuation.operator","."], - ["identifier","clientX"], - ["paren.quasi.end","}"], - ["string.quasi"," !"], - ["string.quasi.end","`"], - ["punctuation.operator",";"] -],[ - ["#tmp","js-block-end","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["text","\t"], - ["paren.rparen","}"] -],[ - ["#tmp","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["paren.rparen","}"] -],[ - ["#tmp","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["constant.language","md"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["paren.lparen","\"\"\""] -],[ - ["#tmp","md-multiline-allowBlock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["markup.list","- "], - ["list","div"] -],[ - ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["markup.list","- "], - ["list","span"] -],[ - ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["list"," "] -],[ - ["#tmp","md-multiline-listblock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["list","Hello"] -],[ - ["#tmp","md-multiline-start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","md-multiline-start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["text","["], - ["string","one"], - ["text","]("], - ["markup.underline","http://google.com"], - ["text",")"] -],[ - ["#tmp","md-multiline-allowBlock","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["paren.rparen","\"\"\";"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["keyword.support.constant.language","header"], - ["text"," "], - ["support.variable.class",".foo"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["string.start","'"], - ["string","Heading"], - ["string.end","'"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["keyword.support.constant.language","button"], - ["text"," "], - ["support.variable.class",".baz"], - ["text"," "], - ["support.variable.class.markup.bold","x-signal"], - ["keyword.operator","="], - ["string.start","'"], - ["string","click: test"], - ["string.end","'"], - ["text"," "], - ["support.variable.class","disabled"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["string.start","\""] -],[ - ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["string","\tHello,"] -],[ - ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["string","\tworld "] -],[ - ["string.start2","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["string","\t"], - ["string.escape","\\\""], - ["string","Buddy"], - ["string.escape","\\\""] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["string.end","\""] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","js-statement-start","start","js-statement-no_regex","constant.language53","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["constant.language","var"], - ["text"," "], - ["identifier","a"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["paren","{"] -],[ - ["#tmp","js-statement-no_regex","start","js-statement-no_regex","constant.language53","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["text"," "], - ["identifier","name"], - ["punctuation.operator",":"], - ["text"," "], - ["string.quasi.start","`"], - ["string.quasi","name "], - ["paren.quasi.start","${"], - ["variable.language","window"], - ["punctuation.operator","."], - ["support.constant","innerWidth"], - ["paren.rparen","}"], - ["string.quasi.end","`"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["paren.rparen","};"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"] -],[ - ["#tmp","start","paren.lparen13","constant.language","constant.language","start","paren.lparen39","constant.language27","constant.language27","start","paren.lparen52","constant.language40"], - ["keyword.support.constant.language","span"], - ["text"," "], - ["support.variable.class",".foo"], - ["text"," "], - ["paren.lparen",">"], - ["text"," "], - ["string.start","\""], - ["paren.lparen.markup.italic","~["], - ["keyword.control.markup.italic","bind:"], - ["text"," "], - ["identifier","a"], - ["punctuation.operator","."], - ["identifier","name"], - ["paren.rparen.markup.italic","]"], - ["string.end","\""] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_matlab.json b/lib/ace/mode/_test/tokens_matlab.json deleted file mode 100644 index 6b4a8567..00000000 --- a/lib/ace/mode/_test/tokens_matlab.json +++ /dev/null @@ -1,90 +0,0 @@ -[[ - ["blockComment","noQstring"], - ["comment.start","%{"] -],[ - ["blockComment","blockComment","blockComment","noQstring"], - ["comment.start"," %{"] -],[ - ["blockComment","blockComment","blockComment","noQstring"], - ["comment"," Ace Matlab demo"] -],[ - ["blockComment","noQstring"], - ["comment.end"," %}"] -],[ - "noQstring", - ["comment.end","%}"] -],[ - "start" -],[ - "start", - ["keyword","classdef"], - ["text"," "], - ["identifier","hello"] -],[ - "start", - ["text"," "], - ["support.function","methods"] -],[ - "start", - ["text"," "], - ["keyword","function"], - ["text"," "], - ["identifier","greet"], - ["paren.lparen","("], - ["identifier","this"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["support.function","disp"], - ["paren.lparen","("], - ["string","'Hello!'"], - ["paren.rparen",")"], - ["text"," "], - ["comment","% say hi"] -],[ - "start", - ["text"," "], - ["keyword","end"] -],[ - "start", - ["text"," "], - ["keyword","end"] -],[ - "start", - ["keyword","end"] -],[ - "noQstring" -],[ - "start", - ["comment","% transpose "] -],[ - "qqstring", - ["identifier","a"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["paren.lparen","["], - ["text"," "], - ["string","'x"], - ["constant.language.escape","''"], - ["string","y'"], - ["punctuation.operator",","], - ["text"," "], - ["string","\"x"], - ["constant.language.escape","\\n"], - ["string","\\"] -],[ - "start", - ["string"," y\""], - ["punctuation.operator",","], - ["text"," "], - ["constant.numeric","1"], - ["text","' "], - ["paren.rparen","]"], - ["text","' "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","2"], - ["text","'"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_mel.json b/lib/ace/mode/_test/tokens_mel.json deleted file mode 100644 index a2d618a9..00000000 --- a/lib/ace/mode/_test/tokens_mel.json +++ /dev/null @@ -1,257 +0,0 @@ -[[ - "start", - ["comment.line.double-slash.mel","//"], - ["punctuation.definition.comment.mel"," animated duplicates, instances script"] -],[ - "start", - ["meta.function.mel","proc"], - ["keyword.other.mel"," "], - ["storage.type.mel","animatedDuplication"], - ["entity.name.function.mel"," ("], - ["punctuation.section.function.mel","("], - ["meta.function.mel","int $rangeStart, int $rangeEnd, int $numOfDuplicates, int $duplicateOrInstance"], - ["punctuation.section.function.mel",")"], - "proc animatedDuplication (int $rangeStart, int $rangeEnd, int $numOfDuplicates, int $duplicateOrInstance)" -],[ - "start", - ["text","{"] -],[ - "start", - ["text"," "], - ["storage.type.mel","int"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","range_start"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","rangeStart"], - ["text",";"] -],[ - "start", - ["text"," "], - ["storage.type.mel","int"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","range_end"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","rangeEnd"], - ["text",";"] -],[ - "start", - ["text"," "], - ["storage.type.mel","int"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","num_of_duplicates"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","numOfDuplicates"], - ["text",";"] -],[ - "start", - ["text"," "], - ["storage.type.mel","int"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","step_size"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," ("], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","range_end"], - ["text"," "], - ["keyword.operator.symbolic.mel","-"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","range_start"], - ["text",") "], - ["keyword.operator.symbolic.mel","/"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","num_of_duplicates"], - ["text",";"] -],[ - "start", - ["text"," "], - ["storage.type.mel","int"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","i"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," "], - ["constant.numeric.mel","0"], - ["text",";"] -],[ - "start", - ["text"," "], - ["storage.type.mel","int"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","temp"], - ["text",";"] -],[ - "start" -],[ - "start", - ["text"," "], - ["support.function.mel","currentTime"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","range_start"], - ["text","; "], - ["comment.line.double-slash.mel","//"], - ["punctuation.definition.comment.mel"," set to range start"] -],[ - "start" -],[ - "start", - ["text"," "], - ["storage.type.mel","string"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","selectedObjects"], - ["text","[]; "], - ["comment.line.double-slash.mel","//"], - ["punctuation.definition.comment.mel"," to store selected objects"] -],[ - "start", - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","selectedObjects"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," `"], - ["support.function.mel","ls"], - ["text"," "], - ["keyword.operator.symbolic.mel","-"], - ["text","sl`; "], - ["comment.line.double-slash.mel","//"], - ["punctuation.definition.comment.mel"," store selected objects"] -],[ - "start", - ["text"," "], - ["support.function.mel","select"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","selectedObjects"], - ["text",";"] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword.control.mel","while"], - ["text"," ("], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","i"], - ["text"," <"], - ["keyword.operator.symbolic.mel","="], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","num_of_duplicates"], - ["text",")"] -],[ - "start", - ["text"," {"] -],[ - "start", - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","temp"], - ["text"," "], - ["keyword.operator.symbolic.mel","="], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","range_start"], - ["text"," "], - ["keyword.operator.symbolic.mel","+"], - ["text"," ("], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","step_size"], - ["text"," "], - ["keyword.operator.symbolic.mel","*"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","i"], - ["text",");"] -],[ - "start", - ["text"," "], - ["support.function.mel","currentTime"], - ["text"," ("], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","temp"], - ["text",");"] -],[ - "start", - ["text"," "], - ["comment.line.double-slash.mel","//"], - ["punctuation.definition.comment.mel"," seleced the objects to duplicate or instance"] -],[ - "start", - ["text"," "], - ["support.function.mel","select"], - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","selectedObjects"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.control.mel","if"], - ["text","("], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","duplicateOrInstance"], - ["text"," "], - ["keyword.operator.symbolic.mel","=="], - ["text"," "], - ["constant.numeric.mel","0"], - ["text",")"] -],[ - "start", - ["text"," {"] -],[ - "start", - ["text"," "], - ["support.function.mel","duplicate"], - ["text",";"] -],[ - "start", - ["text"," }"] -],[ - "start", - ["text"," "], - ["keyword.control.mel","else"] -],[ - "start", - ["text"," {"] -],[ - "start", - ["text"," "], - ["support.function.mel","instance"], - ["text",";"] -],[ - "start", - ["text"," }"] -],[ - "start", - ["text"," "], - ["variable.other.mel","$"], - ["punctuation.definition.variable.mel","i"], - ["keyword.operator.symbolic.mel","++"], - ["text",";"] -],[ - "start", - ["text"," }"] -],[ - "start", - ["text","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_mysql.json b/lib/ace/mode/_test/tokens_mysql.json deleted file mode 100644 index 9909eadd..00000000 --- a/lib/ace/mode/_test/tokens_mysql.json +++ /dev/null @@ -1,4 +0,0 @@ -[[ - "start", - ["identifier","TODO"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_nix.json b/lib/ace/mode/_test/tokens_nix.json deleted file mode 100644 index b9424456..00000000 --- a/lib/ace/mode/_test/tokens_nix.json +++ /dev/null @@ -1,360 +0,0 @@ -[[ - "start", - ["text","{"] -],[ - "start", - ["text"," "], - ["comment","# Name of our deployment"] -],[ - "start", - ["text"," "], - ["identifier","network"], - ["text","."], - ["identifier","description"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","\"HelloWorld\""], - ["text",";"] -],[ - "start", - ["text"," "], - ["comment","# Enable rolling back to previous versions of our infrastructure"] -],[ - "start", - ["text"," "], - ["identifier","network"], - ["text","."], - ["identifier","enableRollback"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["constant.language.nix","true"], - ["text",";"] -],[ - "start" -],[ - "start", - ["text"," "], - ["comment","# It consists of a single server named 'helloserver'"] -],[ - "start", - ["text"," "], - ["identifier","helloserver"], - ["text"," "], - ["keyword.operator.assignment.nix","="] -],[ - "start", - ["text"," "], - ["comment","# Every server gets passed a few arguments, including a reference"] -],[ - "start", - ["text"," "], - ["comment","# to nixpkgs (pkgs)"] -],[ - "start", - ["text"," { "], - ["identifier","config"], - ["text",", "], - ["identifier","pkgs"], - ["text",", ... }:"] -],[ - "start", - ["text"," "], - ["keyword.declaration.nix","let"] -],[ - "start", - ["text"," "], - ["comment","# We import our custom packages from ./default passing pkgs as argument"] -],[ - "start", - ["text"," "], - ["identifier","packages"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["keyword.control.nix","import"], - ["text"," ./"], - ["identifier","default"], - ["text","."], - ["identifier","nix"], - ["text"," { "], - ["identifier","pkgs"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["identifier","pkgs"], - ["text","; };"] -],[ - "start", - ["text"," "], - ["comment","# This is the nodejs version specified in default.nix"] -],[ - "start", - ["text"," "], - ["identifier","nodejs"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["identifier","packages"], - ["text","."], - ["identifier","nodejs"], - ["text",";"] -],[ - "start", - ["text"," "], - ["comment","# And this is the application we'd like to deploy"] -],[ - "start", - ["text"," "], - ["identifier","app"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["identifier","packages"], - ["text","."], - ["identifier","app"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.declaration.nix","in"] -],[ - "start", - ["text"," {"] -],[ - "start", - ["text"," "], - ["comment","# We'll be running our application on port 8080, because a regular"] -],[ - "start", - ["text"," "], - ["comment","# user cannot bind to port 80"] -],[ - "start", - ["text"," "], - ["comment","# Then, using some iptables magic we'll forward traffic designated to port 80 to 8080"] -],[ - "start", - ["text"," "], - ["identifier","networking"], - ["text","."], - ["identifier","firewall"], - ["text","."], - ["identifier","enable"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["constant.language.nix","true"], - ["text",";"] -],[ - "start", - ["text"," "], - ["comment","# We will open up port 22 (SSH) as well otherwise we're locking ourselves out"] -],[ - "start", - ["text"," "], - ["identifier","networking"], - ["text","."], - ["identifier","firewall"], - ["text","."], - ["identifier","allowedTCPPorts"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," [ "], - ["constant.numeric","80"], - ["text"," "], - ["constant.numeric","8080"], - ["text"," "], - ["constant.numeric","22"], - ["text"," ];"] -],[ - "start", - ["text"," "], - ["identifier","networking"], - ["text","."], - ["identifier","firewall"], - ["text","."], - ["identifier","allowPing"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["constant.language.nix","true"], - ["text",";"] -],[ - "start" -],[ - "start", - ["text"," "], - ["comment","# Port forwarding using iptables"] -],[ - "qqdoc", - ["text"," "], - ["identifier","networking"], - ["text","."], - ["identifier","firewall"], - ["text","."], - ["identifier","extraCommands"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","''"] -],[ - "qqdoc", - ["string"," iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080"] -],[ - "start", - ["string"," ''"], - ["text",";"] -],[ - "start" -],[ - "start", - ["text"," "], - ["comment","# To run our node.js program we're going to use a systemd service"] -],[ - "start", - ["text"," "], - ["comment","# We can configure the service to automatically start on boot and to restart"] -],[ - "start", - ["text"," "], - ["comment","# the process in case it crashes"] -],[ - "start", - ["text"," "], - ["identifier","systemd"], - ["text","."], - ["identifier","services"], - ["text","."], - ["identifier","helloserver"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," {"] -],[ - "start", - ["text"," "], - ["identifier","description"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","\"Hello world application\""], - ["text",";"] -],[ - "start", - ["text"," "], - ["comment","# Start the service after the network is available"] -],[ - "start", - ["text"," "], - ["identifier","after"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," [ "], - ["string","\"network.target\""], - ["text"," ];"] -],[ - "start", - ["text"," "], - ["comment","# We're going to run it on port 8080 in production"] -],[ - "start", - ["text"," "], - ["identifier","environment"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," { "], - ["identifier","PORT"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","\"8080\""], - ["text","; };"] -],[ - "start", - ["text"," "], - ["identifier","serviceConfig"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," {"] -],[ - "start", - ["text"," "], - ["comment","# The actual command to run"] -],[ - "start", - ["text"," "], - ["identifier","ExecStart"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","\""], - ["constant.language.escape","${"], - ["identifier","nodejs"], - ["constant.language.escape","}"], - ["string","/bin/node "], - ["constant.language.escape","${"], - ["identifier","app"], - ["constant.language.escape","}"], - ["string","/server.js\""], - ["text",";"] -],[ - "start", - ["text"," "], - ["comment","# For security reasons we'll run this process as a special 'nodejs' user"] -],[ - "start", - ["text"," "], - ["identifier","User"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","\"nodejs\""], - ["text",";"] -],[ - "start", - ["text"," "], - ["identifier","Restart"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," "], - ["string","\"always\""], - ["text",";"] -],[ - "start", - ["text"," };"] -],[ - "start", - ["text"," };"] -],[ - "start" -],[ - "start", - ["text"," "], - ["comment","# And lastly we ensure the user we run our application as is created"] -],[ - "start", - ["text"," "], - ["identifier","users"], - ["text","."], - ["identifier","extraUsers"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," {"] -],[ - "start", - ["text"," "], - ["identifier","nodejs"], - ["text"," "], - ["keyword.operator.assignment.nix","="], - ["text"," { };"] -],[ - "start", - ["text"," };"] -],[ - "start", - ["text"," };"] -],[ - "start", - ["text","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_objectivec.json b/lib/ace/mode/_test/tokens_objectivec.json index cdfd1196..c6582d20 100644 --- a/lib/ace/mode/_test/tokens_objectivec.json +++ b/lib/ace/mode/_test/tokens_objectivec.json @@ -727,8 +727,7 @@ ],[ "start", ["keyword","#ifndef"], - ["text"," "], - ["constant.language.objc","Nil"] + ["constant.other"," Nil"] ],[ "start", ["keyword","#define"], diff --git a/lib/ace/mode/_test/tokens_pgsql.json b/lib/ace/mode/_test/tokens_pgsql.json index fef23fd2..ded4bb86 100644 --- a/lib/ace/mode/_test/tokens_pgsql.json +++ b/lib/ace/mode/_test/tokens_pgsql.json @@ -297,10 +297,10 @@ ["comment.doc","* Dollar quotes starting at the end of the line are colored as SQL unless"] ],[ "doc-start", - ["comment.doc","* a special language tag is used. Dollar quote syntax coloring is implemented"] + ["comment.doc","* a special language tag is used. Pearl and Python are currently implemented"] ],[ "doc-start", - ["comment.doc","* for Perl, Python, JavaScript, and Json."] + ["comment.doc","* but lots of others are possible."] ],[ "start", ["comment.doc","*/"] @@ -662,160 +662,6 @@ ["statementEnd",";"] ],[ "start" -],[ - "start", - ["comment","-- pl/v8 (javascript)"] -],[ - "javascript-start", - ["keyword.statementBegin","CREATE"], - ["text"," "], - ["keyword","FUNCTION"], - ["text"," "], - ["identifier","plv8_test"], - ["paren.lparen","("], - ["identifier","keys"], - ["text"," "], - ["keyword","text"], - ["text","[], "], - ["identifier","vals"], - ["text"," "], - ["keyword","text"], - ["text","[]"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","RETURNS"], - ["text"," "], - ["keyword","text"], - ["text"," "], - ["keyword","AS"], - ["text"," "], - ["string","$javascript$"] -],[ - "javascript-start", - ["storage.type","var"], - ["text"," "], - ["identifier","o"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["paren.lparen","{"], - ["paren.rparen","}"], - ["punctuation.operator",";"] -],[ - "javascript-start", - ["keyword","for"], - ["paren.lparen","("], - ["storage.type","var"], - ["text"," "], - ["identifier","i"], - ["keyword.operator","="], - ["constant.numeric","0"], - ["punctuation.operator",";"], - ["text"," "], - ["identifier","i"], - ["keyword.operator","<"], - ["identifier","keys"], - ["punctuation.operator","."], - ["support.constant","length"], - ["punctuation.operator",";"], - ["text"," "], - ["identifier","i"], - ["keyword.operator","++"], - ["paren.rparen",")"], - ["paren.lparen","{"] -],[ - "javascript-start", - ["text"," "], - ["identifier","o"], - ["paren.lparen","["], - ["identifier","keys"], - ["paren.lparen","["], - ["identifier","i"], - ["paren.rparen","]]"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["identifier","vals"], - ["paren.lparen","["], - ["identifier","i"], - ["paren.rparen","]"], - ["punctuation.operator",";"] -],[ - "javascript-no_regex", - ["paren.rparen","}"] -],[ - "javascript-start", - ["keyword","return"], - ["text"," "], - ["variable.language","JSON"], - ["punctuation.operator","."], - ["identifier","stringify"], - ["paren.lparen","("], - ["identifier","o"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start", - ["string","$javascript$"], - ["text"," "], - ["keyword","LANGUAGE"], - ["text"," "], - ["identifier","plv8"], - ["text"," "], - ["keyword","IMMUTABLE"], - ["text"," "], - ["keyword","STRICT"], - ["statementEnd",";"] -],[ - "start" -],[ - "start", - ["comment","-- json"] -],[ - "json-start", - ["keyword.statementBegin","select"], - ["text"," "], - ["keyword.operator","*"], - ["text"," "], - ["keyword","from"], - ["text"," "], - ["support.function","json_object_keys"], - ["paren.lparen","("], - ["string","$json$"] -],[ - "json-start", - ["paren.lparen","{"] -],[ - "json-start", - ["text"," "], - ["variable","\"f1\""], - ["text",": "], - ["constant.numeric","5"], - ["text",","] -],[ - "json-start", - ["text"," "], - ["variable","\"f2\""], - ["text",": "], - ["string","\"test\""], - ["text",","] -],[ - "json-start", - ["text"," "], - ["variable","\"f3\""], - ["text",": "], - ["paren.lparen","{"], - ["paren.rparen","}"] -],[ - "json-start", - ["paren.rparen","}"] -],[ - "start", - ["string","$json$"], - ["paren.rparen",")"], - ["statementEnd",";"] -],[ - "start" ],[ "start" ],[ diff --git a/lib/ace/mode/_test/tokens_php.json b/lib/ace/mode/_test/tokens_php.json index 2134dccb..d8a41eec 100644 --- a/lib/ace/mode/_test/tokens_php.json +++ b/lib/ace/mode/_test/tokens_php.json @@ -128,44 +128,7 @@ ["text",";"] ],[ "php-start" -],[ - ["php-start","js-start"], - ["support.php_tag","?>"], - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.script.tag-name.xml","script"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text"," "], - ["support.php_tag",""] -],[ - "js-comment_regex_allowed", - ["comment","/*this is js "], - ["support.php_tag",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," not "], - ["constant.language.escape.reference.xml","&js;"] -],[ - "start" + ["support.php_tag","?>"] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_prolog.json b/lib/ace/mode/_test/tokens_prolog.json index 4c0f5c5c..e42b65b5 100644 --- a/lib/ace/mode/_test/tokens_prolog.json +++ b/lib/ace/mode/_test/tokens_prolog.json @@ -117,67 +117,85 @@ "start", ["text"," "] ],[ - "start", + "entity.name.function.fact.prolog", ["entity.name.function.fact.prolog","quicksort"], ["punctuation.begin.fact.parameters.prolog","("], ["punctuation.begin.list.prolog","["], ["punctuation.end.list.prolog","]"], - ["punctuation.end.fact.parameters.prolog",")"], - ["text"," --> []."] + ["invalid.illegal.invalidchar.prolog",")"], + ["meta.fact.prolog"," "], + ["invalid.illegal.invalidchar.prolog","-"], + ["keyword.operator.prolog","->"], + ["meta.fact.prolog"," "], + ["punctuation.begin.list.prolog","["], + ["punctuation.end.list.prolog","]"], + ["invalid.illegal.invalidchar.prolog","."] ],[ - "start", - ["entity.name.function.fact.prolog","quicksort"], - ["punctuation.begin.fact.parameters.prolog","("], + "entity.name.function.fact.prolog", + ["constant.other.atom.prolog","quicksort"], + ["punctuation.begin.statement.parameters.prolog","("], ["punctuation.begin.list.prolog","["], ["variable.other.prolog","X"], ["punctuation.concat.list.prolog","|"], ["variable.other.prolog","Xs"], ["punctuation.end.list.prolog","]"], - ["punctuation.end.fact.parameters.prolog",")"], - ["text"," -->"] + ["punctuation.end.statement.parameters.prolog",")"], + ["meta.fact.prolog"," "], + ["invalid.illegal.invalidchar.prolog","-"], + ["keyword.operator.prolog","->"] ],[ - "start", - ["text"," { "], - ["entity.name.function.fact.prolog","partition"], - ["punctuation.begin.fact.parameters.prolog","("], - ["variable.parameter.prolog","Xs"], + "entity.name.function.fact.prolog", + ["meta.fact.prolog"," "], + ["invalid.illegal.invalidchar.prolog","{"], + ["meta.fact.prolog"," "], + ["constant.other.atom.prolog","partition"], + ["punctuation.begin.statement.parameters.prolog","("], + ["variable.other.prolog","Xs"], + ["punctuation.separator.statement.prolog",","], + ["meta.statement.parameters.prolog"," "], + ["variable.other.prolog","X"], + ["punctuation.separator.statement.prolog",","], + ["meta.statement.parameters.prolog"," "], + ["variable.other.prolog","Smaller"], + ["punctuation.separator.statement.prolog",","], + ["meta.statement.parameters.prolog"," "], + ["variable.other.prolog","Bigger"], + ["punctuation.end.statement.parameters.prolog",")"], + ["meta.fact.prolog"," "], + ["invalid.illegal.invalidchar.prolog","}"], + ["punctuation.separator.parameters.prolog",","] +],[ + "entity.name.function.fact.prolog", + ["meta.fact.prolog"," "], + ["constant.other.atom.prolog","quicksort"], + ["punctuation.begin.statement.parameters.prolog","("], + ["variable.other.prolog","Smaller"], + ["punctuation.end.statement.parameters.prolog",")"], ["punctuation.separator.parameters.prolog",","], ["meta.fact.prolog"," "], - ["variable.parameter.prolog","X"], + ["punctuation.begin.list.prolog","["], + ["variable.other.prolog","X"], + ["punctuation.end.list.prolog","]"], ["punctuation.separator.parameters.prolog",","], ["meta.fact.prolog"," "], - ["variable.parameter.prolog","Smaller"], - ["punctuation.separator.parameters.prolog",","], + ["constant.other.atom.prolog","quicksort"], + ["punctuation.begin.statement.parameters.prolog","("], + ["variable.other.prolog","Bigger"], + ["punctuation.end.statement.parameters.prolog",")"], + ["invalid.illegal.invalidchar.prolog","."] +],[ + "entity.name.function.fact.prolog" +],[ + "entity.name.function.fact.prolog", + ["constant.other.atom.prolog","perfect"], + ["punctuation.begin.statement.parameters.prolog","("], + ["variable.other.prolog","N"], + ["punctuation.end.statement.parameters.prolog",")"], ["meta.fact.prolog"," "], - ["variable.parameter.prolog","Bigger"], - ["punctuation.end.fact.parameters.prolog",")"], - ["text"," },"] + ["invalid.illegal.invalidchar.prolog",":-"] ],[ - "start", - ["text"," "], - ["entity.name.function.fact.prolog","quicksort"], - ["punctuation.begin.fact.parameters.prolog","("], - ["variable.parameter.prolog","Smaller"], - ["punctuation.end.fact.parameters.prolog",")"], - ["text",", [X], "], - ["entity.name.function.fact.prolog","quicksort"], - ["punctuation.begin.fact.parameters.prolog","("], - ["variable.parameter.prolog","Bigger"], - ["punctuation.end.fact.parameters.prolog",")"], - ["punctuation.end.fact.prolog","."] -],[ - "start" -],[ - ["keyword.operator.definition.prolog","meta.rule.prolog"], - ["entity.name.function.rule.prolog","perfect"], - ["punctuation.rule.parameters.begin.prolog","("], - ["variable.parameter.prolog","N"], - ["punctuation.rule.parameters.end.prolog",")"], - ["meta.rule.signature.prolog"," "], - ["keyword.operator.definition.prolog",":-"] -],[ - ["keyword.operator.definition.prolog","meta.rule.prolog"], - ["meta.rule.definition.prolog"," "], + "entity.name.function.fact.prolog", + ["meta.fact.prolog"," "], ["constant.other.atom.prolog","between"], ["punctuation.begin.statement.parameters.prolog","("], ["constant.numeric.prolog","1"], @@ -188,19 +206,21 @@ ["meta.statement.parameters.prolog"," "], ["variable.other.prolog","N"], ["punctuation.end.statement.parameters.prolog",")"], - ["punctuation.control.and.prolog",","], - ["meta.rule.definition.prolog"," "], - ["variable.other.prolog","U"], - ["meta.rule.definition.prolog"," "], + ["punctuation.separator.parameters.prolog",","], + ["meta.fact.prolog"," "], + ["variable.parameter.prolog","U"], + ["meta.fact.prolog"," "], ["keyword.operator.prolog","is"], - ["meta.rule.definition.prolog"," "], - ["variable.other.prolog","N"], - ["meta.rule.definition.prolog"," // "], + ["meta.fact.prolog"," "], + ["variable.parameter.prolog","N"], + ["meta.fact.prolog"," "], + ["invalid.illegal.invalidchar.prolog","//"], + ["meta.fact.prolog"," "], ["constant.numeric.prolog","2"], - ["punctuation.control.and.prolog",","] + ["punctuation.separator.parameters.prolog",","] ],[ - ["keyword.operator.definition.prolog","meta.rule.prolog"], - ["meta.rule.definition.prolog"," "], + "entity.name.function.fact.prolog", + ["meta.fact.prolog"," "], ["constant.other.atom.prolog","findall"], ["punctuation.begin.statement.parameters.prolog","("], ["variable.other.prolog","D"], @@ -226,14 +246,14 @@ ["meta.statement.parameters.prolog"," "], ["constant.numeric.prolog","0"], ["punctuation.end.statement.parameters.prolog",")"], - ["punctuation.control.and.prolog",","], - ["meta.rule.definition.prolog"," "], - ["variable.other.prolog","Ds"], - ["meta.rule.definition.prolog",")"], - ["punctuation.control.and.prolog",","] + ["punctuation.separator.parameters.prolog",","], + ["meta.fact.prolog"," "], + ["variable.parameter.prolog","Ds"], + ["invalid.illegal.invalidchar.prolog",")"], + ["punctuation.separator.parameters.prolog",","] ],[ - "start", - ["meta.rule.definition.prolog"," "], + "entity.name.function.fact.prolog", + ["meta.fact.prolog"," "], ["constant.other.atom.prolog","sumlist"], ["punctuation.begin.statement.parameters.prolog","("], ["variable.other.prolog","Ds"], @@ -241,5 +261,5 @@ ["meta.statement.parameters.prolog"," "], ["variable.other.prolog","N"], ["punctuation.end.statement.parameters.prolog",")"], - ["punctuation.rule.end.prolog","."] + ["invalid.illegal.invalidchar.prolog","."] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_protobuf.json b/lib/ace/mode/_test/tokens_protobuf.json deleted file mode 100644 index 469dba06..00000000 --- a/lib/ace/mode/_test/tokens_protobuf.json +++ /dev/null @@ -1,136 +0,0 @@ -[[ - "start", - ["keyword.declaration.protobuf","message"], - ["text"," "], - ["identifier","Point"], - ["text"," {"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","required"], - ["text"," "], - ["support.type","int32"], - ["text"," "], - ["identifier","x"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","1"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","required"], - ["text"," "], - ["support.type","int32"], - ["text"," "], - ["identifier","y"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","2"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","optional"], - ["text"," "], - ["support.type","string"], - ["text"," "], - ["identifier","label"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","3"], - ["text",";"] -],[ - "start", - ["text","}"] -],[ - "start" -],[ - "start", - ["keyword.declaration.protobuf","message"], - ["text"," "], - ["identifier","Line"], - ["text"," {"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","required"], - ["text"," "], - ["identifier","Point"], - ["text"," "], - ["identifier","start"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","1"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","required"], - ["text"," "], - ["identifier","Point"], - ["text"," "], - ["identifier","end"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","2"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","optional"], - ["text"," "], - ["support.type","string"], - ["text"," "], - ["identifier","label"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","3"], - ["text",";"] -],[ - "start", - ["text","}"] -],[ - "start" -],[ - "start", - ["keyword.declaration.protobuf","message"], - ["text"," "], - ["identifier","Polyline"], - ["text"," {"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","repeated"], - ["text"," "], - ["identifier","Point"], - ["text"," "], - ["identifier","point"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","1"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword.declaration.protobuf","optional"], - ["text"," "], - ["support.type","string"], - ["text"," "], - ["identifier","label"], - ["text"," "], - ["keyword.operator.assignment.protobuf","="], - ["text"," "], - ["constant.numeric","2"], - ["text",";"] -],[ - "start", - ["text","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_rhtml.json b/lib/ace/mode/_test/tokens_rhtml.json index a536f851..6dca1c51 100644 --- a/lib/ace/mode/_test/tokens_rhtml.json +++ b/lib/ace/mode/_test/tokens_rhtml.json @@ -1,55 +1,55 @@ [[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","html"], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","head"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","head"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Title"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","title"], + ["meta.tag.punctuation.end",">"], + ["text","Title"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","body"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","body"], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","This is an R HTML document. When you click the "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","b"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Knit HTML"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["text.xml"," button a web page will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text","This is an R HTML document. When you click the "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","b"], + ["meta.tag.punctuation.end",">"], + ["text","Knit HTML"], + ["meta.tag.punctuation.begin",""], + ["text"," button a web page will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:"], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ @@ -68,13 +68,13 @@ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","p"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","You can also embed plots, for example:"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","p"], + ["meta.tag.punctuation.end",">"], + ["text","You can also embed plots, for example:"], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ @@ -93,14 +93,14 @@ "start" ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_ruby.json b/lib/ace/mode/_test/tokens_ruby.json index f9991e9c..19b98b70 100644 --- a/lib/ace/mode/_test/tokens_ruby.json +++ b/lib/ace/mode/_test/tokens_ruby.json @@ -139,24 +139,14 @@ ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string.character","?\""], + ["constant.numeric","34"], ["text",", "], ["constant.other.symbol.ruby",":key"], ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string.start","\""], - ["string","value"], - ["string.end","\""], - ["text",", "], - ["identifier","anotherKey"], - ["text",": "], - ["paren.lparen","["], - ["identifier","x"], - ["text",", "], - ["identifier","y"], - ["text","?"], - ["paren.rparen","]}"] + ["string","\"value\""], + ["paren.rparen","}"] ],[ "start" ],[ diff --git a/lib/ace/mode/_test/tokens_rust.json b/lib/ace/mode/_test/tokens_rust.json index 8c59a3aa..6592575b 100644 --- a/lib/ace/mode/_test/tokens_rust.json +++ b/lib/ace/mode/_test/tokens_rust.json @@ -10,9 +10,10 @@ ],[ "start", ["keyword.source.rust","fn"], - ["text"," "], + ["meta.function.source.rust"," "], ["entity.name.function.source.rust","main"], - ["text","() {"] + ["meta.function.source.rust","("], + ["text",") {"] ],[ "start", ["text"," "], @@ -87,14 +88,10 @@ ],[ "start", ["keyword.source.rust","fn"], - ["text"," "], - ["entity.name.function.source.rust","map"], - ["keyword.operator","<"], - ["text","T"], - ["keyword.operator",","], - ["text"," U"], - ["keyword.operator",">"], - ["text","(vector: &[T]"], + ["meta.function.source.rust"," "], + ["entity.name.function.source.rust","map"], + ["meta.function.source.rust","("], + ["text","vector: &[T]"], ["keyword.operator",","], ["text"," function: &fn(v: &T) "], ["keyword.operator","->"], diff --git a/lib/ace/mode/_test/tokens_sh.json b/lib/ace/mode/_test/tokens_sh.json index f2c6b276..e4ab3412 100644 --- a/lib/ace/mode/_test/tokens_sh.json +++ b/lib/ace/mode/_test/tokens_sh.json @@ -11,13 +11,13 @@ ["comment","# Repo formats:"] ],[ "start", - ["comment","# ssh git@github.com:richo/gh_pr.git"] + ["comment","# ssh git@github.com:richoH/gh_pr.git"] ],[ "start", - ["comment","# http https://richoH@github.com/richo/gh_pr.git"] + ["comment","# http https://richoH@github.com/richoH/gh_pr.git"] ],[ "start", - ["comment","# git git://github.com/richo/gh_pr.git"] + ["comment","# git git://github.com/richoH/gh_pr.git"] ],[ "start" ],[ diff --git a/lib/ace/mode/_test/tokens_sjs.json b/lib/ace/mode/_test/tokens_sjs.json deleted file mode 100644 index 5cd96451..00000000 --- a/lib/ace/mode/_test/tokens_sjs.json +++ /dev/null @@ -1,276 +0,0 @@ -[[ - "start", - ["storage.type","var"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["identifier","each"], - ["punctuation.operator",","], - ["text"," "], - ["identifier","map"], - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["identifier","require"], - ["paren.lparen","("], - ["string","'sjs:sequence'"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start", - ["storage.type","var"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["keyword","get"], - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["identifier","require"], - ["paren.lparen","("], - ["string","'sjs:http'"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start" -],[ - "start", - ["storage.type","function"], - ["text"," "], - ["entity.name.function","foo"], - ["paren.lparen","("], - ["variable.parameter","items"], - ["punctuation.operator",", "], - ["variable.parameter","nada"], - ["paren.rparen",")"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["no_regex"], - ["text"," "], - ["storage.type","var"], - ["text"," "], - ["identifier","component"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["identifier","name"], - ["punctuation.operator",":"], - ["text"," "], - ["string","\"Ace\""], - ["punctuation.operator",","], - ["text"," "], - ["identifier","role"], - ["punctuation.operator",":"], - ["text"," "], - ["string","\"Editor\""], - ["text"," "], - ["paren.rparen","}"], - ["punctuation.operator",";"] -],[ - ["qqstring","no_regex"], - ["text"," "], - ["storage.type","console"], - ["punctuation.operator","."], - ["support.function.firebug","log"], - ["paren.lparen","("], - ["string","\""] -],[ - ["qqstring","no_regex"], - ["string"," Welcome, "], - ["paren.lparen","#{"], - ["identifier","component"], - ["text","."], - ["identifier","name"], - ["paren.rparen","}"] -],[ - ["no_regex"], - ["string"," \""], - ["punctuation.operator","."], - ["identifier","trim"], - ["paren.lparen","("], - ["paren.rparen","))"], - ["punctuation.operator",";"] -],[ - ["no_regex"] -],[ - ["no_regex"], - ["text"," "], - ["identifier","logging"], - ["punctuation.operator","."], - ["identifier","debug"], - ["paren.lparen","("], - ["string","`Component added: "], - ["paren.lparen","$"], - ["identifier","String"], - ["paren.lparen","("], - ["identifier","component"], - ["paren.rparen",")"], - ["string"," ("], - ["paren.lparen","${"], - ["identifier","component"], - ["paren.rparen","}"], - ["string",")`"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - ["no_regex"] -],[ - ["bstring","no_regex"], - ["text"," "], - ["storage.type","console"], - ["punctuation.operator","."], - ["support.function.firebug","log"], - ["paren.lparen","("], - ["string","`"] -],[ - ["string_interp","string_interp","bstring","no_regex"], - ["string"," Welcome, {"], - ["paren.lparen","${"], - ["storage.type","function"], - ["text","() "], - ["paren.lparen","{"] -],[ - ["string_interp","string_interp","bstring","no_regex"], - ["text"," "], - ["keyword","return"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["identifier","x"], - ["text",": "], - ["constant.numeric","1"], - ["text",", "], - ["identifier","y"], - ["text",": "], - ["string","\"why?}\""], - ["paren.rparen","}"], - ["text",";"] -],[ - ["bstring","no_regex"], - ["text"," "], - ["paren.rparen","}"], - ["text","()"], - ["paren.rparen","}"] -],[ - ["no_regex"], - ["string"," `"], - ["punctuation.operator","."], - ["identifier","trim"], - ["paren.lparen","("], - ["paren.rparen","))"], - ["punctuation.operator",";"] -],[ - ["no_regex"] -],[ - ["no_regex"], - ["text"," "], - ["keyword","waitfor"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["no_regex"], - ["text"," "], - ["identifier","items"], - ["text"," "], - ["keyword.operator",".."], - ["text"," "], - ["identifier","each"], - ["punctuation.operator","."], - ["identifier","par"], - ["text"," "], - ["paren.lparen","{"], - ["text"," "], - ["paren.rparen","|"], - ["variable.parameter","item"], - ["paren.rparen","|"] -],[ - ["no_regex"], - ["text"," "], - ["keyword","get"], - ["paren.lparen","("], - ["identifier","item"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - ["no_regex"], - ["text"," "], - ["paren.rparen","}"] -],[ - ["no_regex"], - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword","and"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["no_regex"], - ["text"," "], - ["storage.type","var"], - ["text"," "], - ["identifier","lengths"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["identifier","items"], - ["text"," "], - ["keyword.operator",".."], - ["text"," "], - ["identifier","map"], - ["paren.lparen","("], - ["identifier","i"], - ["text"," "], - ["keyword.operator","->"], - ["text"," "], - ["identifier","i"], - ["punctuation.operator","."], - ["support.constant","length"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - ["no_regex"], - ["text"," "], - ["paren.rparen","}"], - ["text"," "], - ["keyword","or"], - ["text"," "], - ["paren.lparen","{"] -],[ - ["no_regex"], - ["text"," "], - ["variable.language","hold"], - ["paren.lparen","("], - ["constant.numeric","1500"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - ["no_regex"], - ["text"," "], - ["keyword","throw"], - ["text"," "], - ["keyword","new"], - ["text"," "], - ["variable.language","Error"], - ["paren.lparen","("], - ["string","\"timed out\""], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - ["no_regex"], - ["text"," "], - ["paren.rparen","}"] -],[ - ["no_regex"], - ["paren.rparen","}"], - ["text","\t"], - ["comment","// Real Tab."] -],[ - ["no_regex"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_smarty.json b/lib/ace/mode/_test/tokens_smarty.json deleted file mode 100644 index 0f56985d..00000000 --- a/lib/ace/mode/_test/tokens_smarty.json +++ /dev/null @@ -1,98 +0,0 @@ -[[ - "start", - ["punctuation.section.embedded.begin.smarty","{"], - ["keyword.control.smarty","foreach"], - ["source.smarty"," "], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","foo"], - ["source.smarty"," as "], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["punctuation.section.embedded.end.smarty","}"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], - ["punctuation.section.embedded.begin.smarty","{"], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["source.smarty",".zig"], - ["punctuation.section.embedded.end.smarty","}"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["punctuation.section.embedded.begin.smarty","{"], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["source.smarty",".zag"], - ["punctuation.section.embedded.end.smarty","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], - ["punctuation.section.embedded.begin.smarty","{"], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["source.smarty",".zig2"], - ["punctuation.section.embedded.end.smarty","}"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["punctuation.section.embedded.begin.smarty","{"], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["source.smarty",".zag2"], - ["punctuation.section.embedded.end.smarty","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], - ["punctuation.section.embedded.begin.smarty","{"], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["source.smarty",".zig3"], - ["punctuation.section.embedded.end.smarty","}"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["punctuation.section.embedded.begin.smarty","{"], - ["punctuation.definition.variable.smarty","$"], - ["variable.other.smarty","bar"], - ["source.smarty",".zag3"], - ["punctuation.section.embedded.end.smarty","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] -],[ - "start", - ["punctuation.section.embedded.begin.smarty","{"], - ["keyword.control.smarty","foreachelse"], - ["punctuation.section.embedded.end.smarty","}"] -],[ - "start", - ["text.xml"," There were no rows found."] -],[ - "start", - ["punctuation.section.embedded.begin.smarty","{"], - ["source.smarty","/"], - ["keyword.control.smarty","foreach"], - ["punctuation.section.embedded.end.smarty","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_soy_template.json b/lib/ace/mode/_test/tokens_soy_template.json deleted file mode 100644 index 9ae7c4ed..00000000 --- a/lib/ace/mode/_test/tokens_soy_template.json +++ /dev/null @@ -1,286 +0,0 @@ -[[ - "punctuation.definition.comment.begin.soy1", - ["punctuation.definition.comment.begin.soy","/**"] -],[ - "punctuation.definition.comment.begin.soy1", - ["comment.block.documentation.soy"," * Greets a person using \"Hello\" by default."] -],[ - "punctuation.definition.comment.begin.soy1", - ["comment.block.documentation.soy"," * "], - ["support.type.soy","@param"], - ["text"," "], - ["variable.parameter.soy","name"], - ["comment.block.documentation.soy"," The name of the person."] -],[ - "punctuation.definition.comment.begin.soy1", - ["comment.block.documentation.soy"," * "], - ["support.type.soy","@param?"], - ["text"," "], - ["variable.parameter.soy","greetingWord"], - ["comment.block.documentation.soy"," Optional greeting word to use instead of \"Hello\"."] -],[ - "start", - ["comment.block.documentation.soy"," "], - ["punctuation.definition.comment.end.soy","*/"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","template"], - ["text"," "], - ["entity.name.function.soy",".helloName"], - ["meta.tag.template.soy"," #eee"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","if"], - ["meta.tag.if.soy"," "], - ["keyword.operator.soy","not"], - ["meta.tag.if.soy"," "], - ["variable.other.soy","$greetingWord"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," Hello "], - ["punctuation.definition.tag.begin.soy","{"], - ["variable.other.soy","$name"], - ["punctuation.definition.tag.end.soy","}"], - ["text.xml","!"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["text","else"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["variable.other.soy","$greetingWord"], - ["punctuation.definition.tag.end.soy","}"], - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["variable.other.soy","$name"], - ["punctuation.definition.tag.end.soy","}"], - ["text.xml","!"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{/"], - ["entity.name.tag.soy","if"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{/"], - ["meta.tag.template.soy","template"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start" -],[ - "punctuation.definition.comment.begin.soy1", - ["punctuation.definition.comment.begin.soy","/**"] -],[ - "punctuation.definition.comment.begin.soy1", - ["comment.block.documentation.soy"," * Greets a person and optionally a list of other people."] -],[ - "punctuation.definition.comment.begin.soy1", - ["comment.block.documentation.soy"," * "], - ["support.type.soy","@param"], - ["text"," "], - ["variable.parameter.soy","name"], - ["comment.block.documentation.soy"," The name of the person."] -],[ - "punctuation.definition.comment.begin.soy1", - ["comment.block.documentation.soy"," * "], - ["support.type.soy","@param"], - ["text"," "], - ["variable.parameter.soy","additionalNames"], - ["comment.block.documentation.soy"," The additional names to greet. May be an empty list."] -],[ - "start", - ["comment.block.documentation.soy"," "], - ["punctuation.definition.comment.end.soy","*/"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","template"], - ["text"," "], - ["entity.name.function.soy",".helloNames"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["comment.line.double-slash.soy"," "], - ["punctuation.definition.comment.soy","//"], - ["comment.line.double-slash.soy"," Greet the person."] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","call"], - ["variable.parameter.soy"," .helloName"], - ["meta.tag.call.soy"," "], - ["entity.other.attribute-name.soy","data"], - ["keyword.operator.soy","="], - ["string.quoted.double","\"all\""], - ["meta.tag.call.soy"," /"], - ["punctuation.definition.tag.end.soy","}"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","br"], - ["meta.tag.punctuation.tag-close.xml",">"] -],[ - "start", - ["comment.line.double-slash.soy"," "], - ["punctuation.definition.comment.soy","//"], - ["comment.line.double-slash.soy"," Greet the additional people."] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","foreach"], - ["meta.tag.foreach.soy"," "], - ["variable.other.soy","$additionalName"], - ["meta.tag.foreach.soy"," "], - ["keyword.operator.soy","in"], - ["meta.tag.foreach.soy"," "], - ["variable.other.soy","$additionalNames"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","call"], - ["variable.parameter.soy"," .helloName"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","param"], - ["meta.tag.param.soy"," "], - ["entity.other.attribute-name.soy","name"], - ["keyword.operator.soy",":"], - ["meta.tag.param.soy"," "], - ["variable.other.soy","$additionalName"], - ["meta.tag.param.soy"," /"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{/"], - ["meta.tag.call.soy","call"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","if"], - ["meta.tag.if.soy"," "], - ["keyword.operator.soy","not"], - ["meta.tag.if.soy"," "], - ["support.function.soy","isLast"], - ["meta.tag.if.soy","("], - ["variable.other.soy","$additionalName"], - ["meta.tag.if.soy",")"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","br"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["comment.line.double-slash.soy"," "], - ["punctuation.definition.comment.soy","//"], - ["comment.line.double-slash.soy"," break after every line except the last"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{/"], - ["entity.name.tag.soy","if"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{"], - ["text","ifempty"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," No additional people to greet."] -],[ - "start", - ["text.xml"," "], - ["punctuation.definition.tag.begin.soy","{/"], - ["entity.name.tag.soy","foreach"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{/"], - ["meta.tag.template.soy","template"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start" -],[ - "start" -],[ - "start", - ["punctuation.definition.tag.begin.soy","{/"], - ["entity.name.tag.soy","foreach"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","if"], - ["meta.tag.if.soy"," "], - ["support.function.soy","length"], - ["meta.tag.if.soy","("], - ["variable.other.soy","$items"], - ["meta.tag.if.soy",") > 5"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","msg"], - ["meta.tag.msg.soy"," "], - ["entity.other.attribute-name.soy","desc"], - ["keyword.operator.soy","="], - ["string.quoted.double","\"Says hello to the user.\""], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start" -],[ - "start" -],[ - "start", - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","namespace"], - ["text"," "], - ["variable.parameter.soy","ns"], - ["text"," autoescape=\"contextual\""], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start" -],[ - "start", - ["punctuation.definition.comment.begin.soy","/**"], - ["comment.block.documentation.soy"," Example. "], - ["punctuation.definition.comment.end.soy","*/"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{"], - ["entity.name.tag.soy","template"], - ["text"," "], - ["entity.name.function.soy",".example"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["text.xml"," foo is "], - ["punctuation.definition.tag.begin.soy","{"], - ["variable.other.soy","$ij.foo"], - ["punctuation.definition.tag.end.soy","}"] -],[ - "start", - ["punctuation.definition.tag.begin.soy","{/"], - ["meta.tag.template.soy","template"], - ["punctuation.definition.tag.end.soy","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_space.json b/lib/ace/mode/_test/tokens_space.json deleted file mode 100644 index 918b9a67..00000000 --- a/lib/ace/mode/_test/tokens_space.json +++ /dev/null @@ -1,322 +0,0 @@ -[[ - "start", - ["variable","query"] -],[ - "start", - ["empty_line"," "], - ["variable","count"], - ["keyword.operator"," "], - ["string","10"] -],[ - "start", - ["empty_line"," "], - ["variable","created"], - ["keyword.operator"," "], - ["string","2011-06-21T08:10:46Z"] -],[ - "start", - ["empty_line"," "], - ["variable","lang"], - ["keyword.operator"," "], - ["string","en-US"] -],[ - "start", - ["empty_line"," "], - ["variable","results"] -],[ - "start", - ["empty_line"," "], - ["variable","photo"] -],[ - "start", - ["empty_line"," "], - ["variable","0"] -],[ - "start", - ["empty_line"," "], - ["variable","farm"], - ["keyword.operator"," "], - ["string","6"] -],[ - "start", - ["empty_line"," "], - ["variable","id"], - ["keyword.operator"," "], - ["string","5855620975"] -],[ - "start", - ["empty_line"," "], - ["variable","isfamily"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","isfriend"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","ispublic"], - ["keyword.operator"," "], - ["string","1"] -],[ - "start", - ["empty_line"," "], - ["variable","owner"], - ["keyword.operator"," "], - ["string","32021554@N04"] -],[ - "start", - ["empty_line"," "], - ["variable","secret"], - ["keyword.operator"," "], - ["string","f1f5e8515d"] -],[ - "start", - ["empty_line"," "], - ["variable","server"], - ["keyword.operator"," "], - ["string","5110"] -],[ - "start", - ["empty_line"," "], - ["variable","title"], - ["keyword.operator"," "], - ["string","7087 bandit cat"] -],[ - "start", - ["empty_line"," "], - ["variable","1"] -],[ - "start", - ["empty_line"," "], - ["variable","farm"], - ["keyword.operator"," "], - ["string","4"] -],[ - "start", - ["empty_line"," "], - ["variable","id"], - ["keyword.operator"," "], - ["string","5856170534"] -],[ - "start", - ["empty_line"," "], - ["variable","isfamily"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","isfriend"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","ispublic"], - ["keyword.operator"," "], - ["string","1"] -],[ - "start", - ["empty_line"," "], - ["variable","owner"], - ["keyword.operator"," "], - ["string","32021554@N04"] -],[ - "start", - ["empty_line"," "], - ["variable","secret"], - ["keyword.operator"," "], - ["string","ff1efb2a6f"] -],[ - "start", - ["empty_line"," "], - ["variable","server"], - ["keyword.operator"," "], - ["string","3217"] -],[ - "start", - ["empty_line"," "], - ["variable","title"], - ["keyword.operator"," "], - ["string","6975 rusty cat"] -],[ - "start", - ["empty_line"," "], - ["variable","2"] -],[ - "start", - ["empty_line"," "], - ["variable","farm"], - ["keyword.operator"," "], - ["string","6"] -],[ - "start", - ["empty_line"," "], - ["variable","id"], - ["keyword.operator"," "], - ["string","5856172972"] -],[ - "start", - ["empty_line"," "], - ["variable","isfamily"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","isfriend"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","ispublic"], - ["keyword.operator"," "], - ["string","1"] -],[ - "start", - ["empty_line"," "], - ["variable","owner"], - ["keyword.operator"," "], - ["string","51249875@N03"] -],[ - "start", - ["empty_line"," "], - ["variable","secret"], - ["keyword.operator"," "], - ["string","6c6887347c"] -],[ - "start", - ["empty_line"," "], - ["variable","server"], - ["keyword.operator"," "], - ["string","5192"] -],[ - "start", - ["empty_line"," "], - ["variable","title"], - ["keyword.operator"," "], - ["string","watermarked-cats"] -],[ - "start", - ["empty_line"," "], - ["variable","3"] -],[ - "start", - ["empty_line"," "], - ["variable","farm"], - ["keyword.operator"," "], - ["string","6"] -],[ - "start", - ["empty_line"," "], - ["variable","id"], - ["keyword.operator"," "], - ["string","5856168328"] -],[ - "start", - ["empty_line"," "], - ["variable","isfamily"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","isfriend"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","ispublic"], - ["keyword.operator"," "], - ["string","1"] -],[ - "start", - ["empty_line"," "], - ["variable","owner"], - ["keyword.operator"," "], - ["string","32021554@N04"] -],[ - "start", - ["empty_line"," "], - ["variable","secret"], - ["keyword.operator"," "], - ["string","0c1cfdf64c"] -],[ - "start", - ["empty_line"," "], - ["variable","server"], - ["keyword.operator"," "], - ["string","5078"] -],[ - "start", - ["empty_line"," "], - ["variable","title"], - ["keyword.operator"," "], - ["string","7020 mandy cat"] -],[ - "start", - ["empty_line"," "], - ["variable","4"] -],[ - "start", - ["empty_line"," "], - ["variable","farm"], - ["keyword.operator"," "], - ["string","3"] -],[ - "start", - ["empty_line"," "], - ["variable","id"], - ["keyword.operator"," "], - ["string","5856171774"] -],[ - "start", - ["empty_line"," "], - ["variable","isfamily"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","isfriend"], - ["keyword.operator"," "], - ["string","0"] -],[ - "start", - ["empty_line"," "], - ["variable","ispublic"], - ["keyword.operator"," "], - ["string","1"] -],[ - "start", - ["empty_line"," "], - ["variable","owner"], - ["keyword.operator"," "], - ["string","32021554@N04"] -],[ - "start", - ["empty_line"," "], - ["variable","secret"], - ["keyword.operator"," "], - ["string","7f5a3180ab"] -],[ - "start", - ["empty_line"," "], - ["variable","server"], - ["keyword.operator"," "], - ["string","2696"] -],[ - "start", - ["empty_line"," "], - ["variable","title"], - ["keyword.operator"," "], - ["string","7448 bobby cat"] -],[ - "key" -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_svg.json b/lib/ace/mode/_test/tokens_svg.json index 66ebae75..f92fbbb6 100644 --- a/lib/ace/mode/_test/tokens_svg.json +++ b/lib/ace/mode/_test/tokens_svg.json @@ -1,65 +1,65 @@ [[ - "meta.tag.punctuation.tag-open.xml1", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","svg"] + "meta.tag.punctuation.begin0", + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","svg"] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","width"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"800\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","height"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"600\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","width"], + ["keyword.operator.separator","="], + ["string","\"800\""], + ["text"," "], + ["entity.other.attribute-name","height"], + ["keyword.operator.separator","="], + ["string","\"600\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","xmlns"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"http://www.w3.org/2000/svg\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","xmlns"], + ["keyword.operator.separator","="], + ["string","\"http://www.w3.org/2000/svg\""] ],[ "start", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","onload"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"StartAnimation(evt)\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["entity.other.attribute-name","onload"], + ["keyword.operator.separator","="], + ["string","\"StartAnimation(evt)\""], + ["meta.tag.punctuation.end",">"] ],[ "start" ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Test Tube Progress Bar"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","title"], + ["meta.tag.punctuation.end",">"], + ["text","Test Tube Progress Bar"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","desc"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","Created for the Web Directions SVG competition"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","desc"], + ["meta.tag.punctuation.end",">"], + ["text","Created for the Web Directions SVG competition"], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "js-no_regex", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.script.tag-name.xml","script"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","type"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"text/ecmascript\""], - ["meta.tag.punctuation.tag-close.xml",">"], - ["string.cdata.xml",""], + ["string.begin",""], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["string.end","]]>"], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","rect"] + "meta.tag.punctuation.begin0", + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","rect"] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","fill"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"#2e3436\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","fill"], + ["keyword.operator.separator","="], + ["string","\"#2e3436\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","fill-rule"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"nonzero\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","fill-rule"], + ["keyword.operator.separator","="], + ["string","\"nonzero\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","stroke-width"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"3\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","stroke-width"], + ["keyword.operator.separator","="], + ["string","\"3\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","y"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"0\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","y"], + ["keyword.operator.separator","="], + ["string","\"0\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","x"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"0\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","x"], + ["keyword.operator.separator","="], + ["string","\"0\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","height"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"600\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","height"], + ["keyword.operator.separator","="], + ["string","\"600\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","width"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"800\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","width"], + ["keyword.operator.separator","="], + ["string","\"800\""] ],[ "start", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"rect3590\""], - ["meta.tag.punctuation.tag-close.xml","/>"] + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"rect3590\""], + ["meta.tag.punctuation.end","/>"] ],[ "start" ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","text"] + "meta.tag.punctuation.begin0", + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","text"] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","style"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"font-size:144px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","style"], + ["keyword.operator.separator","="], + ["string","\"font-size:144px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","x"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"50\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","x"], + ["keyword.operator.separator","="], + ["string","\"50\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","y"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"350\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","y"], + ["keyword.operator.separator","="], + ["string","\"350\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"hickory\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"hickory\""] ],[ "start", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","display"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"none\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["entity.other.attribute-name","display"], + ["keyword.operator.separator","="], + ["string","\"none\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," Hickory,"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," Hickory,"], + ["meta.tag.punctuation.begin",""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","text"] + "meta.tag.punctuation.begin0", + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","text"] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","style"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"font-size:144px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","style"], + ["keyword.operator.separator","="], + ["string","\"font-size:144px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","x"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"50\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","x"], + ["keyword.operator.separator","="], + ["string","\"50\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","y"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"350\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","y"], + ["keyword.operator.separator","="], + ["string","\"350\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"dickory\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"dickory\""] ],[ "start", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","display"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"none\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["entity.other.attribute-name","display"], + ["keyword.operator.separator","="], + ["string","\"none\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," dickory,"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," dickory,"], + ["meta.tag.punctuation.begin",""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","text"] + "meta.tag.punctuation.begin0", + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","text"] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","style"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"font-size:144px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","style"], + ["keyword.operator.separator","="], + ["string","\"font-size:144px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","x"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"50\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","x"], + ["keyword.operator.separator","="], + ["string","\"50\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","y"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"350\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","y"], + ["keyword.operator.separator","="], + ["string","\"350\""] ],[ - "meta.tag.punctuation.tag-open.xml1", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"dock\""] + "meta.tag.punctuation.begin0", + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"dock\""] ],[ "start", - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","display"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"none\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["entity.other.attribute-name","display"], + ["keyword.operator.separator","="], + ["string","\"none\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," dock!"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," dock!"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_twig.json b/lib/ace/mode/_test/tokens_twig.json index ada8b4a7..c4101ded 100644 --- a/lib/ace/mode/_test/tokens_twig.json +++ b/lib/ace/mode/_test/tokens_twig.json @@ -1,56 +1,56 @@ [[ "start", - ["xml-pe.doctype.xml",""] + ["punctuation.doctype.begin",""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","html"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","html"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","head"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","head"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","title"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","My Webpage"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","title"], + ["meta.tag.punctuation.end",">"], + ["text","My Webpage"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","body"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","body"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","ul"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","id"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"navigation\""], - ["meta.tag.punctuation.tag-close.xml",">"] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","ul"], + ["text"," "], + ["entity.other.attribute-name","id"], + ["keyword.operator.separator","="], + ["string","\"navigation\""], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag.twig","{%"], ["text"," "], ["keyword.control.twig","for"], @@ -64,16 +64,16 @@ ["meta.tag.twig","%}"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","li"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.anchor.tag-name.xml","a"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","href"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\""], + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","li"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.anchor","a"], + ["text"," "], + ["entity.other.attribute-name","href"], + ["keyword.operator.separator","="], + ["string","\""], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["identifier","item"], @@ -83,8 +83,8 @@ ["support.function.twig","escape"], ["text"," "], ["variable.other.readwrite.local.twig","}}"], - ["string.attribute-value.xml","\""], - ["meta.tag.punctuation.tag-close.xml",">"], + ["string","\""], + ["meta.tag.punctuation.end",">"], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["identifier","item"], @@ -92,15 +92,15 @@ ["identifier","caption"], ["text"," "], ["variable.other.readwrite.local.twig","}}"], - ["meta.tag.punctuation.end-tag-open.xml",""], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag.twig","{%"], ["text"," "], ["keyword.control.twig","endfor"], @@ -108,15 +108,15 @@ ["meta.tag.twig","%}"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag.twig","{%"], ["text"," "], ["keyword.control.twig","if"], @@ -142,11 +142,11 @@ "start" ],[ "start", - ["text.xml"," "], + ["text"," "], ["comment.block.twig","{# is equivalent to #}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag.twig","{%"], ["text"," "], ["keyword.control.twig","if"], @@ -173,7 +173,7 @@ "start" ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag.twig","{%"], ["text"," "], ["keyword.control.twig","autoescape"], @@ -183,7 +183,7 @@ ["meta.tag.twig","%}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["identifier","var"], @@ -191,7 +191,7 @@ ["variable.other.readwrite.local.twig","}}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["identifier","var"], @@ -199,11 +199,11 @@ ["support.function.twig","raw"], ["text"," "], ["variable.other.readwrite.local.twig","}}"], - ["text.xml"," "], + ["text"," "], ["comment.block.twig","{# var won't be escaped #}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["identifier","var"], @@ -211,11 +211,11 @@ ["support.function.twig","escape"], ["text"," "], ["variable.other.readwrite.local.twig","}}"], - ["text.xml"," "], + ["text"," "], ["comment.block.twig","{# var won't be doubled-escaped #}"] ],[ "start", - ["text.xml"," "], + ["text"," "], ["meta.tag.twig","{%"], ["text"," "], ["keyword.control.twig","endautoescape"], @@ -225,7 +225,7 @@ "start" ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["keyword.control.twig","include"], @@ -245,7 +245,7 @@ "start" ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable.other.readwrite.local.twig","{{"], ["string","\"string "], ["constant.language.escape","#{with}"], @@ -258,17 +258,17 @@ ["variable.other.readwrite.local.twig","}}"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","h1"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","My Webpage"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","h1"], + ["meta.tag.punctuation.end",">"], + ["text","My Webpage"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml"," "], + ["text"," "], ["variable.other.readwrite.local.twig","{{"], ["text"," "], ["identifier","a_variable"], @@ -276,13 +276,13 @@ ["variable.other.readwrite.local.twig","}}"] ],[ "start", - ["text.xml"," "], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["text"," "], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_vala.json b/lib/ace/mode/_test/tokens_vala.json deleted file mode 100644 index efe6e7c8..00000000 --- a/lib/ace/mode/_test/tokens_vala.json +++ /dev/null @@ -1,158 +0,0 @@ -[[ - "start", - ["meta.using.vala",""], - ["keyword.other.using.vala","using"], - ["meta.using.vala"," "], - ["storage.modifier.using.vala","Gtk"], - ["punctuation.terminator.vala",";"] -],[ - "start", - ["text"," "] -],[ - "text0", - ["storage.type.primitive.array.vala","int"], - ["text"," main ("], - ["storage.type.primitive.array.vala","string"], - ["text","[] args) {"] -],[ - "text0", - ["text"," "], - ["storage.type.vala","Gtk"], - ["keyword.operator.dereference.vala","."], - ["text","init ("], - ["storage.modifier.vala","ref"], - ["text"," args)"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," "], - ["storage.type.primitive.vala","var"], - ["text"," foo "], - ["keyword.operator.assignment.vala","="], - ["text"," "], - ["keyword.control.new.vala","new"], - ["text"," "], - ["storage.type.generic.vala","MyFoo>"], - ["text","()"], - ["punctuation.terminator.vala",";"] -],[ - "text0" -],[ - "text0", - ["text"," "], - ["storage.type.primitive.vala","var"], - ["text"," window "], - ["keyword.operator.assignment.vala","="], - ["text"," "], - ["keyword.control.new.vala","new"], - ["text"," "], - ["storage.type.vala","Window"], - ["text","()"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","title "], - ["keyword.operator.assignment.vala","="], - ["text"," "], - ["punctuation.definition.string.begin.vala","\""], - ["string.quoted.double.vala","Hello, World!"], - ["punctuation.definition.string.end.vala","\""], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","border_width "], - ["keyword.operator.assignment.vala","="], - ["text"," "], - ["constant.numeric.vala","10"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","window_position "], - ["keyword.operator.assignment.vala","="], - ["text"," "], - ["storage.type.vala","WindowPosition"], - ["keyword.operator.dereference.vala","."], - ["constant.other.vala","CENTER"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","set_default_size("], - ["constant.numeric.vala","350"], - ["text",", "], - ["constant.numeric.vala","70"], - ["text",")"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","destroy"], - ["keyword.operator.dereference.vala","."], - ["text","connect("], - ["storage.type.vala","Gtk"], - ["keyword.operator.dereference.vala","."], - ["text","main_quit)"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," "] -],[ - "text0", - ["text"," "], - ["storage.type.primitive.vala","var"], - ["text"," label "], - ["keyword.operator.assignment.vala","="], - ["text"," "], - ["keyword.control.new.vala","new"], - ["text"," "], - ["storage.type.vala","Label"], - ["text","("], - ["punctuation.definition.string.begin.vala","\""], - ["string.quoted.double.vala","Hello, World!"], - ["punctuation.definition.string.end.vala","\""], - ["text",")"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," "] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","add(label)"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," window"], - ["keyword.operator.dereference.vala","."], - ["text","show_all()"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," "] -],[ - "text0", - ["text"," "], - ["storage.type.vala","Gtk"], - ["keyword.operator.dereference.vala","."], - ["text","main()"], - ["punctuation.terminator.vala",";"] -],[ - "text0", - ["text"," "], - ["keyword.control.vala","return"], - ["text"," "], - ["constant.numeric.vala","0"], - ["punctuation.terminator.vala",";"] -],[ - "start", - ["text","}"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_vbscript.json b/lib/ace/mode/_test/tokens_vbscript.json index 05d5dd22..6a2346d3 100644 --- a/lib/ace/mode/_test/tokens_vbscript.json +++ b/lib/ace/mode/_test/tokens_vbscript.json @@ -5,12 +5,18 @@ ["text"," "], ["punctuation.definition.string.begin.asp","\""], ["string.quoted.double.asp","C:\\Wikipedia - VBScript - Example - Hello World.txt\""] +],[ + "start" ],[ "start", ["text","MakeHelloWorldFile myfilename"] +],[ + "start" ],[ "state_4", ["meta.leading-space"," "] +],[ + "state_4" ],[ "start", ["storage.type.function.asp","Sub"], @@ -20,10 +26,14 @@ ["punctuation.definition.parameters.asp","("], ["variable.parameter.function.asp","FileName"], ["punctuation.definition.parameters.asp",")"] +],[ + "start" ],[ "start", ["punctuation.definition.comment.asp","'"], ["comment.line.apostrophe.asp","Create a new file in C: drive or overwrite existing file"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -37,6 +47,8 @@ ["punctuation.definition.string.begin.asp","\""], ["string.quoted.double.asp","Scripting.FileSystemObject\""], ["text",")"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -47,6 +59,8 @@ ["text","(FileName) "], ["keyword.control.asp","Then"], ["text"," "] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -67,6 +81,8 @@ ["punctuation.definition.string.begin.asp","\""], ["string.quoted.double.asp"," exists ... OK to overwrite?\""], ["text",", vbOKCancel)"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -74,6 +90,8 @@ ["meta.odd-tab.spaces"," "], ["punctuation.definition.comment.asp","'"], ["comment.line.apostrophe.asp","If button selected is not OK, then quit now"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -81,6 +99,8 @@ ["meta.odd-tab.spaces"," "], ["punctuation.definition.comment.asp","'"], ["comment.line.apostrophe.asp","vbOK is a language constant"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -93,11 +113,15 @@ ["keyword.control.asp","Then"], ["text"," "], ["keyword.control.asp","Exit Sub"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], ["meta.leading-space"," "], ["keyword.control.asp","Else"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -105,6 +129,8 @@ ["meta.odd-tab.spaces"," "], ["punctuation.definition.comment.asp","'"], ["comment.line.apostrophe.asp","Confirm OK to create"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -125,6 +151,8 @@ ["punctuation.definition.string.begin.asp","\""], ["string.quoted.double.asp"," ... OK to create?\""], ["text",", vbOKCancel)"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -137,17 +165,23 @@ ["keyword.control.asp","Then"], ["text"," "], ["keyword.control.asp","Exit Sub"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], ["meta.leading-space"," "], ["keyword.control.asp","End If"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], ["meta.leading-space"," "], ["punctuation.definition.comment.asp","'"], ["comment.line.apostrophe.asp","Create new file (or replace an existing file)"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -156,6 +190,8 @@ ["text"," FileObject "], ["keyword.operator.asp","="], ["text"," FSO.CreateTextFile (FileName)"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -168,6 +204,8 @@ ["text"," "], ["support.function.vb.asp","Now"], ["text","()"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -175,6 +213,8 @@ ["text","FileObject.WriteLine "], ["punctuation.definition.string.begin.asp","\""], ["string.quoted.double.asp","Hello World\""] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -182,6 +222,8 @@ ["text","FileObject."], ["entity.name.function.asp","Close"], ["text","()"] +],[ + "start" ],[ "start", ["meta.odd-tab.spaces"," "], @@ -197,7 +239,11 @@ ["text"," "], ["punctuation.definition.string.begin.asp","\""], ["string.quoted.double.asp"," ... updated.\""] +],[ + "start" ],[ "start", - ["storage.type.asp","End Sub"] + ["support.function.asp","End"], + ["text"," "], + ["storage.type.asp","Sub"] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_velocity.json b/lib/ace/mode/_test/tokens_velocity.json index ee40761c..3eb7a9ab 100644 --- a/lib/ace/mode/_test/tokens_velocity.json +++ b/lib/ace/mode/_test/tokens_velocity.json @@ -26,15 +26,15 @@ ],[ "start", ["text"," "], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","li"], - ["meta.tag.punctuation.tag-close.xml",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","li"], + ["meta.tag.punctuation.end",">"], ["variable","${"], ["identifier","item"], ["variable","}"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start", ["keyword","#end"] @@ -55,14 +55,11 @@ ["text"," "], ["lparen","["], ["constant.numeric","1"], - ["text.xml",","], - ["text"," "], + ["text",", "], ["constant.numeric","2"], - ["text.xml",","], - ["text"," "], + ["text",", "], ["constant.numeric","3"], - ["text.xml",","], - ["text"," "], + ["text",", "], ["constant.numeric","4"], ["rparen","]"], ["text"," "], @@ -71,9 +68,9 @@ "start" ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","ul"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","ul"], + ["meta.tag.punctuation.end",">"] ],[ "start", ["text"," "], @@ -100,12 +97,11 @@ ["lparen","("], ["text"," "], ["support.function","$_MathTool"], - ["text.xml","."], + ["text","."], ["identifier","mod"], ["lparen","("], ["variable","$item"], - ["text.xml",","], - ["text"," "], + ["text",", "], ["constant.numeric","2"], ["rparen",")"], ["text"," "], @@ -132,16 +128,16 @@ ["keyword","#end"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "js-start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.script.tag-name.xml","script"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.script","script"], + ["meta.tag.punctuation.end",">"] ],[ "js-comment_regex_allowed", ["text"," "], @@ -220,16 +216,16 @@ ["paren.rparen","}"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ],[ "start" ],[ "css-start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.style.tag-name.xml","style"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name.style","style"], + ["meta.tag.punctuation.end",">"] ],[ ["css-comment","css-start"], ["text"," "], @@ -279,7 +275,7 @@ ["paren.rparen","}"] ],[ "start", - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin",""] ]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_verilog.json b/lib/ace/mode/_test/tokens_verilog.json deleted file mode 100644 index 9680a964..00000000 --- a/lib/ace/mode/_test/tokens_verilog.json +++ /dev/null @@ -1,113 +0,0 @@ -[[ - "start", - ["keyword","always"], - ["text"," @"], - ["paren.lparen","("], - ["keyword","negedge"], - ["text"," "], - ["identifier","reset"], - ["text"," "], - ["keyword","or"], - ["text"," "], - ["keyword","posedge"], - ["text"," "], - ["identifier","clk"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","begin"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["text"," "], - ["paren.lparen","("], - ["identifier","reset"], - ["text"," "], - ["keyword.operator","=="], - ["text"," "], - ["constant.numeric","0"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","begin"] -],[ - "start", - ["text"," "], - ["identifier","d_out"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["constant.numeric","16"], - ["text","'"], - ["identifier","h0000"], - ["text",";"] -],[ - "start", - ["text"," "], - ["identifier","d_out_mem"], - ["text","["], - ["identifier","resetcount"], - ["text","] "], - ["keyword.operator","<="], - ["text"," "], - ["identifier","d_out"], - ["text",";"] -],[ - "start", - ["text"," "], - ["identifier","laststoredvalue"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["identifier","d_out"], - ["text",";"] -],[ - "start", - ["text"," "], - ["keyword","end"], - ["text"," "], - ["keyword","else"], - ["text"," "], - ["keyword","begin"] -],[ - "start", - ["text"," "], - ["identifier","d_out"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["identifier","d_out"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","1"], - ["text","'"], - ["identifier","b1"], - ["text","; "] -],[ - "start", - ["text"," "], - ["keyword","end"] -],[ - "start", - ["keyword","end"] -],[ - "start" -],[ - "start", - ["keyword","always"], - ["text"," @"], - ["paren.lparen","("], - ["identifier","bufreadaddr"], - ["paren.rparen",")"] -],[ - "start", - ["text"," "], - ["identifier","bufreadval"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["identifier","d_out_mem"], - ["text","["], - ["identifier","bufreadaddr"], - ["text","];"] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_vhdl.json b/lib/ace/mode/_test/tokens_vhdl.json deleted file mode 100644 index 88c6e222..00000000 --- a/lib/ace/mode/_test/tokens_vhdl.json +++ /dev/null @@ -1,271 +0,0 @@ -[[ - "start", - ["keyword","library"], - ["text"," "], - ["identifier","IEEE"] -],[ - "start", - ["identifier","user"], - ["text"," "], - ["identifier","IEEE"], - ["punctuation.operator","."], - ["identifier","std_logic_1164"], - ["punctuation.operator","."], - ["keyword","all"], - ["punctuation.operator",";"] -],[ - "start", - ["keyword","use"], - ["text"," "], - ["identifier","IEEE"], - ["punctuation.operator","."], - ["identifier","numeric_std"], - ["punctuation.operator","."], - ["keyword","all"], - ["punctuation.operator",";"] -],[ - "start" -],[ - "start", - ["keyword","entity"], - ["text"," "], - ["identifier","COUNT16"], - ["text"," "], - ["keyword","is"] -],[ - "start" -],[ - "start", - ["text"," "], - ["keyword","port"], - ["text"," "], - ["paren.lparen","("] -],[ - "start", - ["text"," "], - ["identifier","cOut"], - ["text"," "], - ["punctuation.operator",":"], - ["keyword","out"], - ["text"," "], - ["storage.type","std_logic_vector"], - ["paren.lparen","("], - ["constant.numeric","15"], - ["text"," "], - ["keyword","downto"], - ["text"," "], - ["constant.numeric","0"], - ["paren.rparen",")"], - ["punctuation.operator",";"], - ["text"," "], - ["comment","-- counter output"] -],[ - "start", - ["text"," "], - ["identifier","clkEn"], - ["text"," "], - ["punctuation.operator",":"], - ["keyword","in"], - ["text"," "], - ["storage.type","std_logic"], - ["punctuation.operator",";"], - ["text"," "], - ["comment","-- count enable"] -],[ - "start", - ["text"," "], - ["identifier","clk"], - ["text"," "], - ["punctuation.operator",":"], - ["keyword","in"], - ["text"," "], - ["storage.type","std_logic"], - ["punctuation.operator",";"], - ["text"," "], - ["comment","-- clock input"] -],[ - "start", - ["text"," "], - ["identifier","rst"], - ["text"," "], - ["punctuation.operator",":"], - ["keyword","in"], - ["text"," "], - ["storage.type","std_logic"], - ["text"," "], - ["comment","-- reset input"] -],[ - "start", - ["text"," "], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "] -],[ - "start", - ["keyword","end"], - ["text"," "], - ["keyword","entity"], - ["punctuation.operator",";"] -],[ - "start" -],[ - "start", - ["keyword","architecture"], - ["text"," "], - ["identifier","count_rtl"], - ["text"," "], - ["keyword","of"], - ["text"," "], - ["identifier","COUNT16"], - ["text"," "], - ["keyword","is"] -],[ - "start", - ["text"," "], - ["storage.type","signal"], - ["text"," "], - ["identifier","count"], - ["text"," "], - ["punctuation.operator",":"], - ["storage.type","std_logic_vector"], - ["text"," "], - ["paren.lparen","("], - ["constant.numeric","15"], - ["text"," "], - ["keyword","downto"], - ["text"," "], - ["constant.numeric","0"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "] -],[ - "start", - ["keyword","begin"] -],[ - "start", - ["text"," "], - ["keyword","process"], - ["text"," "], - ["paren.lparen","("], - ["identifier","clk"], - ["punctuation.operator",","], - ["text"," "], - ["identifier","rst"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","begin"] -],[ - "start", - ["text"," "] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["paren.lparen","("], - ["identifier","rst"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["string","'1'"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","then"] -],[ - "start", - ["text"," "], - ["identifier","count"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["paren.lparen","("], - ["keyword","others"], - ["keyword.operator","=>"], - ["string","'0'"], - ["paren.rparen",")"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["keyword","elsif"], - ["paren.lparen","("], - ["identifier","rising_edge"], - ["paren.lparen","("], - ["identifier","clk"], - ["paren.rparen","))"], - ["text"," "], - ["keyword","then"] -],[ - "start", - ["text"," "], - ["keyword","if"], - ["paren.lparen","("], - ["identifier","clkEn"], - ["text"," "], - ["keyword.operator","="], - ["text"," "], - ["string","'1'"], - ["paren.rparen",")"], - ["text"," "], - ["keyword","then"] -],[ - "start", - ["text"," "], - ["identifier","count"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["identifier","count"], - ["text"," "], - ["keyword.operator","+"], - ["text"," "], - ["constant.numeric","1"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["keyword","end"], - ["text"," "], - ["keyword","if"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["keyword","end"], - ["text"," "], - ["keyword","if"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "] -],[ - "start", - ["text"," "], - ["keyword","end"], - ["text"," "], - ["keyword","process"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "], - ["identifier","cOut"], - ["text"," "], - ["keyword.operator","<="], - ["text"," "], - ["identifier","count"], - ["punctuation.operator",";"] -],[ - "start" -],[ - "start", - ["keyword","end"], - ["text"," "], - ["keyword","architecture"], - ["punctuation.operator",";"] -],[ - "start", - ["text"," "] -]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_xml.json b/lib/ace/mode/_test/tokens_xml.json index 728be4db..70f73093 100644 --- a/lib/ace/mode/_test/tokens_xml.json +++ b/lib/ace/mode/_test/tokens_xml.json @@ -1,43 +1,43 @@ [[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","Juhu"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["text.xml","//Juhu Kinners"], - ["meta.tag.punctuation.end-tag-open.xml",""] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","Juhu"], + ["meta.tag.punctuation.end",">"], + ["text","//Juhu Kinners"], + ["meta.tag.punctuation.begin",""] ],[ "start", - ["text.xml","test: two tags in the same lines should be in separate tokens\""] + ["text","test: two tags in the same lines should be in separate tokens\""] ],[ "start", - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","Juhu"], - ["meta.tag.punctuation.tag-close.xml",">"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","Kinners"], - ["meta.tag.punctuation.tag-close.xml",">"] + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","Juhu"], + ["meta.tag.punctuation.end",">"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","Kinners"], + ["meta.tag.punctuation.end",">"] ],[ "start", - ["text.xml","test: multiline attributes\""] + ["text","test: multiline attributes\""] ],[ - ["string.attribute-value.xml0","meta.tag.punctuation.tag-open.xml"], - ["meta.tag.punctuation.tag-open.xml","<"], - ["meta.tag.tag-name.xml","copy"], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","set"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"{"] + ["qqstring_inner","meta.tag.punctuation.begin"], + ["meta.tag.punctuation.begin","<"], + ["meta.tag.name","copy"], + ["text"," "], + ["entity.other.attribute-name","set"], + ["keyword.operator.separator","="], + ["string","\"{"] ],[ - ["string.attribute-value.xml0","meta.tag.punctuation.tag-open.xml"], - ["string.attribute-value.xml","}\""], - ["text.tag-whitespace.xml"," "], - ["entity.other.attribute-name.xml","undo"], - ["keyword.operator.attribute-equals.xml","="], - ["string.attribute-value.xml","\"{"] + ["qqstring_inner","meta.tag.punctuation.begin"], + ["string","}\""], + ["text"," "], + ["entity.other.attribute-name","undo"], + ["keyword.operator.separator","="], + ["string","\"{"] ],[ "start", - ["string.attribute-value.xml","}\""], - ["meta.tag.punctuation.tag-close.xml","/>"] + ["string","}\""], + ["meta.tag.punctuation.end","/>"] ]] \ No newline at end of file diff --git a/lib/ace/mode/abap.js b/lib/ace/mode/abap.js index c9d5a991..fbd8066a 100644 --- a/lib/ace/mode/abap.js +++ b/lib/ace/mode/abap.js @@ -31,6 +31,7 @@ define(function(require, exports, module) { "use strict"; +var Tokenizer = require("../tokenizer").Tokenizer; var Rules = require("./abap_highlight_rules").AbapHighlightRules; var FoldMode = require("./folding/coffee").FoldMode; var Range = require("../range").Range; @@ -38,7 +39,9 @@ var TextMode = require("./text").Mode; var oop = require("../lib/oop"); function Mode() { - this.HighlightRules = Rules; + var highlighter = new Rules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$keywordList = new Rules(highlighter.$keywordList); this.foldingRules = new FoldMode(); } @@ -69,7 +72,6 @@ oop.inherits(Mode, TextMode); } }; - this.$id = "ace/mode/abap"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/abap_highlight_rules.js b/lib/ace/mode/abap_highlight_rules.js index bab1e504..6b232c90 100644 --- a/lib/ace/mode/abap_highlight_rules.js +++ b/lib/ace/mode/abap_highlight_rules.js @@ -126,7 +126,7 @@ var AbapHighlightRules = function() { {token : "string", regex : "`", next : "start"}, {defaultToken : "string"} ] - }; + } }; oop.inherits(AbapHighlightRules, TextHighlightRules); diff --git a/lib/ace/mode/abc.js b/lib/ace/mode/abc.js deleted file mode 100644 index b6eb237a..00000000 --- a/lib/ace/mode/abc.js +++ /dev/null @@ -1,58 +0,0 @@ -/* ***** 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; -}); \ No newline at end of file diff --git a/lib/ace/mode/abc_highlight_rules.js b/lib/ace/mode/abc_highlight_rules.js deleted file mode 100644 index 6ffe9c9b..00000000 --- a/lib/ace/mode/abc_highlight_rules.js +++ /dev/null @@ -1,114 +0,0 @@ -/* 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; -}); diff --git a/lib/ace/mode/actionscript.js b/lib/ace/mode/actionscript.js index 7daf2941..7411413d 100644 --- a/lib/ace/mode/actionscript.js +++ b/lib/ace/mode/actionscript.js @@ -27,6 +27,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * + * Contributor(s): + * + * + * * ***** END LICENSE BLOCK ***** */ /* @@ -38,20 +42,22 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var ActionScriptHighlightRules = require("./actionscript_highlight_rules").ActionScriptHighlightRules; // TODO: pick appropriate fold mode var FoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = ActionScriptHighlightRules; + var highlighter = new ActionScriptHighlightRules(); this.foldingRules = new FoldMode(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = "//"; this.blockComment = {start: "/*", end: "*/"}; - this.$id = "ace/mode/actionscript"; + // Extra logic goes here. }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/ada.js b/lib/ace/mode/ada.js index dc1dfa14..8db5a21f 100644 --- a/lib/ace/mode/ada.js +++ b/lib/ace/mode/ada.js @@ -33,11 +33,12 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var AdaHighlightRules = require("./ada_highlight_rules").AdaHighlightRules; var Range = require("../range").Range; var Mode = function() { - this.HighlightRules = AdaHighlightRules; + this.$tokenizer = new Tokenizer(new AdaHighlightRules().getRules()); }; oop.inherits(Mode, TextMode); @@ -45,7 +46,6 @@ oop.inherits(Mode, TextMode); this.lineCommentStart = "--"; - this.$id = "ace/mode/ada"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/apache_conf.js b/lib/ace/mode/apache_conf.js deleted file mode 100644 index 2379b44b..00000000 --- a/lib/ace/mode/apache_conf.js +++ /dev/null @@ -1,62 +0,0 @@ -/* ***** 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. - * - * - * Contributor(s): - * - * - * - * ***** 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 ApacheConfHighlightRules = require("./apache_conf_highlight_rules").ApacheConfHighlightRules; -// TODO: pick appropriate fold mode -var FoldMode = require("./folding/cstyle").FoldMode; - -var Mode = function() { - this.HighlightRules = ApacheConfHighlightRules; - this.foldingRules = new FoldMode(); -}; -oop.inherits(Mode, TextMode); - -(function() { - this.lineCommentStart = "#"; - this.$id = "ace/mode/apache_conf"; - // Extra logic goes here. -}).call(Mode.prototype); - -exports.Mode = Mode; -}); \ No newline at end of file diff --git a/lib/ace/mode/apache_conf_highlight_rules.js b/lib/ace/mode/apache_conf_highlight_rules.js deleted file mode 100644 index c310612d..00000000 --- a/lib/ace/mode/apache_conf_highlight_rules.js +++ /dev/null @@ -1,231 +0,0 @@ -/* ***** 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 from https://raw.github.com/colinta/ApacheConf.tmLanguage/master/ApacheConf.tmLanguage (uuid: ) */ -/**************************************************************************************** - * IT MIGHT NOT BE PERFECT ...But it's a good start from an existing *.tmlanguage file. * - * fileTypes * - ****************************************************************************************/ - -define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; - -var ApacheConfHighlightRules = function() { - // regexp must not have capturing parentheses. Use (?:) instead. - // regexps are ordered -> the first match is used - - this.$rules = { start: - [ { token: - [ 'punctuation.definition.comment.apacheconf', - 'comment.line.hash.ini', - 'comment.line.hash.ini' ], - regex: '^((?:\\s)*)(#)(.*$)' }, - { token: - [ 'punctuation.definition.tag.apacheconf', - 'entity.tag.apacheconf', - 'text', - 'string.value.apacheconf', - 'punctuation.definition.tag.apacheconf' ], - regex: '(<)(Proxy|ProxyMatch|IfVersion|Directory|DirectoryMatch|Files|FilesMatch|IfDefine|IfModule|Limit|LimitExcept|Location|LocationMatch|VirtualHost)(?:(\\s)(.+?))?(>)' }, - { token: - [ 'punctuation.definition.tag.apacheconf', - 'entity.tag.apacheconf', - 'punctuation.definition.tag.apacheconf' ], - regex: '()' }, - { token: - [ 'keyword.alias.apacheconf', 'text', - 'string.regexp.apacheconf', 'text', - 'string.replacement.apacheconf', 'text' ], - regex: '(Rewrite(?:Rule|Cond))(\\s+)(.+?)(\\s+)(.+?)($|\\s)' }, - { token: - [ 'keyword.alias.apacheconf', 'text', - 'entity.status.apacheconf', 'text', - 'string.regexp.apacheconf', 'text', - 'string.path.apacheconf', 'text' ], - regex: '(RedirectMatch)(?:(\\s+)(\\d\\d\\d|permanent|temp|seeother|gone))?(\\s+)(.+?)(\\s+)(?:(.+?)($|\\s))?' }, - { token: - [ 'keyword.alias.apacheconf', 'text', - 'entity.status.apacheconf', 'text', - 'string.path.apacheconf', 'text', - 'string.path.apacheconf', 'text' ], - regex: '(Redirect)(?:(\\s+)(\\d\\d\\d|permanent|temp|seeother|gone))?(\\s+)(.+?)(\\s+)(?:(.+?)($|\\s))?' }, - { token: - [ 'keyword.alias.apacheconf', 'text', - 'string.regexp.apacheconf', 'text', - 'string.path.apacheconf', 'text' ], - regex: '(ScriptAliasMatch|AliasMatch)(\\s+)(.+?)(\\s+)(?:(.+?)(\\s))?' }, - { token: - [ 'keyword.alias.apacheconf', 'text', - 'string.path.apacheconf', 'text', - 'string.path.apacheconf', 'text' ], - regex: '(RedirectPermanent|RedirectTemp|ScriptAlias|Alias)(\\s+)(.+?)(\\s+)(?:(.+?)($|\\s))?' }, - { token: 'keyword.core.apacheconf', - regex: '\\b(?:AcceptPathInfo|AccessFileName|AddDefaultCharset|AddOutputFilterByType|AllowEncodedSlashes|AllowOverride|AuthName|AuthType|CGIMapExtension|ContentDigest|DefaultType|DocumentRoot|EnableMMAP|EnableSendfile|ErrorDocument|ErrorLog|FileETag|ForceType|HostnameLookups|IdentityCheck|Include|KeepAlive|KeepAliveTimeout|LimitInternalRecursion|LimitRequestBody|LimitRequestFields|LimitRequestFieldSize|LimitRequestLine|LimitXMLRequestBody|LogLevel|MaxKeepAliveRequests|NameVirtualHost|Options|Require|RLimitCPU|RLimitMEM|RLimitNPROC|Satisfy|ScriptInterpreterSource|ServerAdmin|ServerAlias|ServerName|ServerPath|ServerRoot|ServerSignature|ServerTokens|SetHandler|SetInputFilter|SetOutputFilter|TimeOut|TraceEnable|UseCanonicalName)\\b' }, - { token: 'keyword.mpm.apacheconf', - regex: '\\b(?:AcceptMutex|AssignUserID|BS2000Account|ChildPerUserID|CoreDumpDirectory|EnableExceptionHook|Group|Listen|ListenBacklog|LockFile|MaxClients|MaxMemFree|MaxRequestsPerChild|MaxRequestsPerThread|MaxSpareServers|MaxSpareThreads|MaxThreads|MaxThreadsPerChild|MinSpareServers|MinSpareThreads|NumServers|PidFile|ReceiveBufferSize|ScoreBoardFile|SendBufferSize|ServerLimit|StartServers|StartThreads|ThreadLimit|ThreadsPerChild|ThreadStackSize|User|Win32DisableAcceptEx)\\b' }, - { token: 'keyword.access.apacheconf', - regex: '\\b(?:Allow|Deny|Order)\\b' }, - { token: 'keyword.actions.apacheconf', - regex: '\\b(?:Action|Script)\\b' }, - { token: 'keyword.alias.apacheconf', - regex: '\\b(?:Alias|AliasMatch|Redirect|RedirectMatch|RedirectPermanent|RedirectTemp|ScriptAlias|ScriptAliasMatch)\\b' }, - { token: 'keyword.auth.apacheconf', - regex: '\\b(?:AuthAuthoritative|AuthGroupFile|AuthUserFile)\\b' }, - { token: 'keyword.auth_anon.apacheconf', - regex: '\\b(?:Anonymous|Anonymous_Authoritative|Anonymous_LogEmail|Anonymous_MustGiveEmail|Anonymous_NoUserID|Anonymous_VerifyEmail)\\b' }, - { token: 'keyword.auth_dbm.apacheconf', - regex: '\\b(?:AuthDBMAuthoritative|AuthDBMGroupFile|AuthDBMType|AuthDBMUserFile)\\b' }, - { token: 'keyword.auth_digest.apacheconf', - regex: '\\b(?:AuthDigestAlgorithm|AuthDigestDomain|AuthDigestFile|AuthDigestGroupFile|AuthDigestNcCheck|AuthDigestNonceFormat|AuthDigestNonceLifetime|AuthDigestQop|AuthDigestShmemSize)\\b' }, - { token: 'keyword.auth_ldap.apacheconf', - regex: '\\b(?:AuthLDAPAuthoritative|AuthLDAPBindDN|AuthLDAPBindPassword|AuthLDAPCharsetConfig|AuthLDAPCompareDNOnServer|AuthLDAPDereferenceAliases|AuthLDAPEnabled|AuthLDAPFrontPageHack|AuthLDAPGroupAttribute|AuthLDAPGroupAttributeIsDN|AuthLDAPRemoteUserIsDN|AuthLDAPUrl)\\b' }, - { token: 'keyword.autoindex.apacheconf', - regex: '\\b(?:AddAlt|AddAltByEncoding|AddAltByType|AddDescription|AddIcon|AddIconByEncoding|AddIconByType|DefaultIcon|HeaderName|IndexIgnore|IndexOptions|IndexOrderDefault|ReadmeName)\\b' }, - { token: 'keyword.cache.apacheconf', - regex: '\\b(?:CacheDefaultExpire|CacheDisable|CacheEnable|CacheForceCompletion|CacheIgnoreCacheControl|CacheIgnoreHeaders|CacheIgnoreNoLastMod|CacheLastModifiedFactor|CacheMaxExpire)\\b' }, - { token: 'keyword.cern_meta.apacheconf', - regex: '\\b(?:MetaDir|MetaFiles|MetaSuffix)\\b' }, - { token: 'keyword.cgi.apacheconf', - regex: '\\b(?:ScriptLog|ScriptLogBuffer|ScriptLogLength)\\b' }, - { token: 'keyword.cgid.apacheconf', - regex: '\\b(?:ScriptLog|ScriptLogBuffer|ScriptLogLength|ScriptSock)\\b' }, - { token: 'keyword.charset_lite.apacheconf', - regex: '\\b(?:CharsetDefault|CharsetOptions|CharsetSourceEnc)\\b' }, - { token: 'keyword.dav.apacheconf', - regex: '\\b(?:Dav|DavDepthInfinity|DavMinTimeout|DavLockDB)\\b' }, - { token: 'keyword.deflate.apacheconf', - regex: '\\b(?:DeflateBufferSize|DeflateCompressionLevel|DeflateFilterNote|DeflateMemLevel|DeflateWindowSize)\\b' }, - { token: 'keyword.dir.apacheconf', - regex: '\\b(?:DirectoryIndex|DirectorySlash)\\b' }, - { token: 'keyword.disk_cache.apacheconf', - regex: '\\b(?:CacheDirLength|CacheDirLevels|CacheExpiryCheck|CacheGcClean|CacheGcDaily|CacheGcInterval|CacheGcMemUsage|CacheGcUnused|CacheMaxFileSize|CacheMinFileSize|CacheRoot|CacheSize|CacheTimeMargin)\\b' }, - { token: 'keyword.dumpio.apacheconf', - regex: '\\b(?:DumpIOInput|DumpIOOutput)\\b' }, - { token: 'keyword.env.apacheconf', - regex: '\\b(?:PassEnv|SetEnv|UnsetEnv)\\b' }, - { token: 'keyword.expires.apacheconf', - regex: '\\b(?:ExpiresActive|ExpiresByType|ExpiresDefault)\\b' }, - { token: 'keyword.ext_filter.apacheconf', - regex: '\\b(?:ExtFilterDefine|ExtFilterOptions)\\b' }, - { token: 'keyword.file_cache.apacheconf', - regex: '\\b(?:CacheFile|MMapFile)\\b' }, - { token: 'keyword.headers.apacheconf', - regex: '\\b(?:Header|RequestHeader)\\b' }, - { token: 'keyword.imap.apacheconf', - regex: '\\b(?:ImapBase|ImapDefault|ImapMenu)\\b' }, - { token: 'keyword.include.apacheconf', - regex: '\\b(?:SSIEndTag|SSIErrorMsg|SSIStartTag|SSITimeFormat|SSIUndefinedEcho|XBitHack)\\b' }, - { token: 'keyword.isapi.apacheconf', - regex: '\\b(?:ISAPIAppendLogToErrors|ISAPIAppendLogToQuery|ISAPICacheFile|ISAPIFakeAsync|ISAPILogNotSupported|ISAPIReadAheadBuffer)\\b' }, - { token: 'keyword.ldap.apacheconf', - regex: '\\b(?:LDAPCacheEntries|LDAPCacheTTL|LDAPConnectionTimeout|LDAPOpCacheEntries|LDAPOpCacheTTL|LDAPSharedCacheFile|LDAPSharedCacheSize|LDAPTrustedCA|LDAPTrustedCAType)\\b' }, - { token: 'keyword.log.apacheconf', - regex: '\\b(?:BufferedLogs|CookieLog|CustomLog|LogFormat|TransferLog|ForensicLog)\\b' }, - { token: 'keyword.mem_cache.apacheconf', - regex: '\\b(?:MCacheMaxObjectCount|MCacheMaxObjectSize|MCacheMaxStreamingBuffer|MCacheMinObjectSize|MCacheRemovalAlgorithm|MCacheSize)\\b' }, - { token: 'keyword.mime.apacheconf', - regex: '\\b(?:AddCharset|AddEncoding|AddHandler|AddInputFilter|AddLanguage|AddOutputFilter|AddType|DefaultLanguage|ModMimeUsePathInfo|MultiviewsMatch|RemoveCharset|RemoveEncoding|RemoveHandler|RemoveInputFilter|RemoveLanguage|RemoveOutputFilter|RemoveType|TypesConfig)\\b' }, - { token: 'keyword.misc.apacheconf', - regex: '\\b(?:ProtocolEcho|Example|AddModuleInfo|MimeMagicFile|CheckSpelling|ExtendedStatus|SuexecUserGroup|UserDir)\\b' }, - { token: 'keyword.negotiation.apacheconf', - regex: '\\b(?:CacheNegotiatedDocs|ForceLanguagePriority|LanguagePriority)\\b' }, - { token: 'keyword.nw_ssl.apacheconf', - regex: '\\b(?:NWSSLTrustedCerts|NWSSLUpgradeable|SecureListen)\\b' }, - { token: 'keyword.proxy.apacheconf', - regex: '\\b(?:AllowCONNECT|NoProxy|ProxyBadHeader|ProxyBlock|ProxyDomain|ProxyErrorOverride|ProxyFtpDirCharset|ProxyIOBufferSize|ProxyMaxForwards|ProxyPass|ProxyPassReverse|ProxyPreserveHost|ProxyReceiveBufferSize|ProxyRemote|ProxyRemoteMatch|ProxyRequests|ProxyTimeout|ProxyVia)\\b' }, - { token: 'keyword.rewrite.apacheconf', - regex: '\\b(?:RewriteBase|RewriteCond|RewriteEngine|RewriteLock|RewriteLog|RewriteLogLevel|RewriteMap|RewriteOptions|RewriteRule)\\b' }, - { token: 'keyword.setenvif.apacheconf', - regex: '\\b(?:BrowserMatch|BrowserMatchNoCase|SetEnvIf|SetEnvIfNoCase)\\b' }, - { token: 'keyword.so.apacheconf', - regex: '\\b(?:LoadFile|LoadModule)\\b' }, - { token: 'keyword.ssl.apacheconf', - regex: '\\b(?:SSLCACertificateFile|SSLCACertificatePath|SSLCARevocationFile|SSLCARevocationPath|SSLCertificateChainFile|SSLCertificateFile|SSLCertificateKeyFile|SSLCipherSuite|SSLEngine|SSLMutex|SSLOptions|SSLPassPhraseDialog|SSLProtocol|SSLProxyCACertificateFile|SSLProxyCACertificatePath|SSLProxyCARevocationFile|SSLProxyCARevocationPath|SSLProxyCipherSuite|SSLProxyEngine|SSLProxyMachineCertificateFile|SSLProxyMachineCertificatePath|SSLProxyProtocol|SSLProxyVerify|SSLProxyVerifyDepth|SSLRandomSeed|SSLRequire|SSLRequireSSL|SSLSessionCache|SSLSessionCacheTimeout|SSLUserName|SSLVerifyClient|SSLVerifyDepth)\\b' }, - { token: 'keyword.usertrack.apacheconf', - regex: '\\b(?:CookieDomain|CookieExpires|CookieName|CookieStyle|CookieTracking)\\b' }, - { token: 'keyword.vhost_alias.apacheconf', - regex: '\\b(?:VirtualDocumentRoot|VirtualDocumentRootIP|VirtualScriptAlias|VirtualScriptAliasIP)\\b' }, - { token: - [ 'keyword.php.apacheconf', - 'text', - 'entity.property.apacheconf', - 'text', - 'string.value.apacheconf', - 'text' ], - regex: '\\b(php_value|php_flag)\\b(?:(\\s+)(.+?)(?:(\\s+)(.+?))?)?(\\s)' }, - { token: - [ 'punctuation.variable.apacheconf', - 'variable.env.apacheconf', - 'variable.misc.apacheconf', - 'punctuation.variable.apacheconf' ], - regex: '(%\\{)(?:(HTTP_USER_AGENT|HTTP_REFERER|HTTP_COOKIE|HTTP_FORWARDED|HTTP_HOST|HTTP_PROXY_CONNECTION|HTTP_ACCEPT|REMOTE_ADDR|REMOTE_HOST|REMOTE_PORT|REMOTE_USER|REMOTE_IDENT|REQUEST_METHOD|SCRIPT_FILENAME|PATH_INFO|QUERY_STRING|AUTH_TYPE|DOCUMENT_ROOT|SERVER_ADMIN|SERVER_NAME|SERVER_ADDR|SERVER_PORT|SERVER_PROTOCOL|SERVER_SOFTWARE|TIME_YEAR|TIME_MON|TIME_DAY|TIME_HOUR|TIME_MIN|TIME_SEC|TIME_WDAY|TIME|API_VERSION|THE_REQUEST|REQUEST_URI|REQUEST_FILENAME|IS_SUBREQ|HTTPS)|(.*?))(\\})' }, - { token: [ 'entity.mime-type.apacheconf', 'text' ], - regex: '\\b((?:text|image|application|video|audio)/.+?)(\\s)' }, - { token: 'entity.helper.apacheconf', - regex: '\\b(?:from|unset|set|on|off)\\b', - caseInsensitive: true }, - { token: 'constant.integer.apacheconf', regex: '\\b\\d+\\b' }, - { token: - [ 'text', - 'punctuation.definition.flag.apacheconf', - 'string.flag.apacheconf', - 'punctuation.definition.flag.apacheconf', - 'text' ], - regex: '(\\s)(\\[)(.*?)(\\])(\\s)' } ] } - - this.normalizeRules(); -}; - -ApacheConfHighlightRules.metaData = { fileTypes: - [ 'conf', - 'CONF', - 'htaccess', - 'HTACCESS', - 'htgroups', - 'HTGROUPS', - 'htpasswd', - 'HTPASSWD', - '.htaccess', - '.HTACCESS', - '.htgroups', - '.HTGROUPS', - '.htpasswd', - '.HTPASSWD' ], - name: 'Apache Conf', - scopeName: 'source.apacheconf' } - - -oop.inherits(ApacheConfHighlightRules, TextHighlightRules); - -exports.ApacheConfHighlightRules = ApacheConfHighlightRules; -}); \ No newline at end of file diff --git a/lib/ace/mode/applescript.js b/lib/ace/mode/applescript.js deleted file mode 100644 index 81bc3533..00000000 --- a/lib/ace/mode/applescript.js +++ /dev/null @@ -1,55 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var TextMode = require("./text").Mode; -var Tokenizer = require("../tokenizer").Tokenizer; -var AppleScriptHighlightRules = require("./applescript_highlight_rules").AppleScriptHighlightRules; -// TODO: pick appropriate fold mode -var FoldMode = require("./folding/cstyle").FoldMode; - -var Mode = function() { - this.HighlightRules = AppleScriptHighlightRules; - this.foldingRules = new FoldMode(); -}; -oop.inherits(Mode, TextMode); - -(function() { - this.lineCommentStart = "--"; - this.blockComment = {start: "(*", end: "*)"}; - this.$id = "ace/mode/applescript"; - // Extra logic goes here. -}).call(Mode.prototype); - -exports.Mode = Mode; -}); diff --git a/lib/ace/mode/applescript_highlight_rules.js b/lib/ace/mode/applescript_highlight_rules.js deleted file mode 100644 index d830d780..00000000 --- a/lib/ace/mode/applescript_highlight_rules.js +++ /dev/null @@ -1,139 +0,0 @@ -/* ***** 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 ***** */ - -define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; - -var AppleScriptHighlightRules = function() { - // regexp must not have capturing parentheses. Use (?:) instead. - // regexps are ordered -> the first match is used - var keywords = ( - "about|above|after|against|and|around|as|at|back|before|beginning|" + - "behind|below|beneath|beside|between|but|by|considering|" + - "contain|contains|continue|copy|div|does|eighth|else|end|equal|" + - "equals|error|every|exit|fifth|first|for|fourth|from|front|" + - "get|given|global|if|ignoring|in|into|is|it|its|last|local|me|" + - "middle|mod|my|ninth|not|of|on|onto|or|over|prop|property|put|ref|" + - "reference|repeat|returning|script|second|set|seventh|since|" + - "sixth|some|tell|tenth|that|the|then|third|through|thru|" + - "timeout|times|to|transaction|try|until|where|while|whose|with|without" - ); - - var builtinConstants = ( - "AppleScript|false|linefeed|return|pi|quote|result|space|tab|true" - ); - - var builtinFunctions = ( - "activate|beep|count|delay|launch|log|offset|read|round|run|say|" + - "summarize|write" - ); - - var builtinTypes = ( - "alias|application|boolean|class|constant|date|file|integer|list|" + - "number|real|record|string|text|character|characters|contents|day|" + - "frontmost|id|item|length|month|name|paragraph|paragraphs|rest|" + - "reverse|running|time|version|weekday|word|words|year" - ); - - var keywordMapper = this.createKeywordMapper({ - "support.function": builtinFunctions, - "constant.language": builtinConstants, - "support.type": builtinTypes, - "keyword": keywords - }, "identifier"); - - this.$rules = { - "start": [ - { - token: "comment", - regex: "--.*$" - }, - { - token : "comment", // multi line comment - regex : "\\(\\*", - next : "comment" - }, - { - token: "string", // " string - regex: '".*?"' - }, - { - token: "support.type", - regex: '\\b(POSIX file|POSIX path|(date|time) string|quoted form)\\b' - }, - { - token: "support.function", - regex: '\\b(clipboard info|the clipboard|info for|list (disks|folder)|' + - 'mount volume|path to|(close|open for) access|(get|set) eof|' + - 'current date|do shell script|get volume settings|random number|' + - 'set volume|system attribute|system info|time to GMT|' + - '(load|run|store) script|scripting components|' + - 'ASCII (character|number)|localized string|' + - 'choose (application|color|file|file name|' + - 'folder|from list|remote application|URL)|' + - 'display (alert|dialog))\\b|^\\s*return\\b' - }, - { - token: "constant.language", - regex: '\\b(text item delimiters|current application|missing value)\\b' - }, - { - token: "keyword", - regex: '\\b(apart from|aside from|instead of|out of|greater than|' + - "isn't|(doesn't|does not) (equal|come before|come after|contain)|" + - '(greater|less) than( or equal)?|(starts?|ends|begins?) with|' + - 'contained by|comes (before|after)|a (ref|reference))\\b' - }, - { - token: keywordMapper, - regex: "[a-zA-Z][a-zA-Z0-9_]*\\b" - } - ], - "comment": [ - { - token: "comment", // closing comment - regex: "\\*\\)", - next: "start" - }, { - defaultToken: "comment" - } - ] - } - - this.normalizeRules(); -}; - -oop.inherits(AppleScriptHighlightRules, TextHighlightRules); - -exports.AppleScriptHighlightRules = AppleScriptHighlightRules; -}); diff --git a/lib/ace/mode/asciidoc.js b/lib/ace/mode/asciidoc.js index 894d9763..be0bf88b 100644 --- a/lib/ace/mode/asciidoc.js +++ b/lib/ace/mode/asciidoc.js @@ -33,12 +33,14 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var AsciidocHighlightRules = require("./asciidoc_highlight_rules").AsciidocHighlightRules; var AsciidocFoldMode = require("./folding/asciidoc").FoldMode; var Mode = function() { - this.HighlightRules = AsciidocHighlightRules; + var highlighter = new AsciidocHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); this.foldingRules = new AsciidocFoldMode(); }; oop.inherits(Mode, TextMode); @@ -57,7 +59,6 @@ oop.inherits(Mode, TextMode); return this.$getIndent(line); } }; - this.$id = "ace/mode/asciidoc"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/assembly_x86.js b/lib/ace/mode/assembly_x86.js index d6343e80..e4d6d8f7 100644 --- a/lib/ace/mode/assembly_x86.js +++ b/lib/ace/mode/assembly_x86.js @@ -38,18 +38,20 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var AssemblyX86HighlightRules = require("./assembly_x86_highlight_rules").AssemblyX86HighlightRules; var FoldMode = require("./folding/coffee").FoldMode; var Mode = function() { - this.HighlightRules = AssemblyX86HighlightRules; + var highlighter = new AssemblyX86HighlightRules(); this.foldingRules = new FoldMode(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = ";"; - this.$id = "ace/mode/assembly_x86"; + // Extra logic goes here. }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/autohotkey.js b/lib/ace/mode/autohotkey.js index d7093fd5..b8e69fd9 100644 --- a/lib/ace/mode/autohotkey.js +++ b/lib/ace/mode/autohotkey.js @@ -26,6 +26,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * + * Contributor(s): + * + * + * * ***** END LICENSE BLOCK ***** */ /* @@ -37,20 +42,22 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var AutoHotKeyHighlightRules = require("./autohotkey_highlight_rules").AutoHotKeyHighlightRules; // TODO: pick appropriate fold mode var FoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = AutoHotKeyHighlightRules; + var highlighter = new AutoHotKeyHighlightRules(); this.foldingRules = new FoldMode(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); (function() { - this.lineCommentStart = ";"; + this.lineCommentStart = "/\\*"; this.blockComment = {start: "/*", end: "*/"}; - this.$id = "ace/mode/autohotkey"; + // Extra logic goes here. }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/batchfile.js b/lib/ace/mode/batchfile.js index e080464c..5b293c0b 100644 --- a/lib/ace/mode/batchfile.js +++ b/lib/ace/mode/batchfile.js @@ -42,19 +42,21 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var BatchFileHighlightRules = require("./batchfile_highlight_rules").BatchFileHighlightRules; var FoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = BatchFileHighlightRules; + var highlighter = new BatchFileHighlightRules(); this.foldingRules = new FoldMode(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = "::"; this.blockComment = ""; - this.$id = "ace/mode/batchfile"; + // Extra logic goes here. }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js deleted file mode 100644 index 245edf99..00000000 --- a/lib/ace/mode/behaviour/behaviour_test.js +++ /dev/null @@ -1,179 +0,0 @@ -/* ***** 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 ***** */ - -if (typeof process !== "undefined") { - require("amd-loader"); - require("../../test/mockdom"); -} - -define(function(require, exports, module) { -"use strict"; - -require("../../multi_select"); -var assert = require("../../test/assertions"); -var Range = require("../../range").Range; -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 { - editor.commands.exec(name, editor, args); - } while(times --> 1); -}; -var testRanges = function(str) { - assert.equal(editor.selection.getAllRanges() + "", str + ""); -}; - -module.exports = { - "test: cstyle": function() { - function testValue(line) { - assert.equal(editor.getValue(), Array(4).join(line + "\n")); - } - function testSelection(line, col, inc) { - editor.selection.rangeList.ranges.forEach(function(r) { - assert.range(r, line, col, line, col); - line += (inc || 1); - }); - } - var doc = new EditSession([ - "", - "", - "", - "" - ], new JavaScriptMode()); - editor = new Editor(new MockRenderer(), doc); - editor.setOption("behavioursEnabled", true); - - editor.navigateFileStart(); - exec("addCursorBelow", 2); - - exec("insertstring", 1, "if "); - - // pairing ( - exec("insertstring", 1, "("); - testValue("if ()"); - testSelection(0, 4); - exec("insertstring", 1, ")"); - testValue("if ()"); - testSelection(0, 5); - - // pairing [ - exec("gotoleft", 1); - exec("insertstring", 1, "["); - testValue("if ([])"); - testSelection(0, 5); - - exec("insertstring", 1, "]"); - testValue("if ([])"); - testSelection(0, 6); - - // test deletion - exec("gotoleft", 1); - exec("backspace", 1); - testValue("if ()"); - testSelection(0, 4); - - exec("gotolineend", 1); - exec("insertstring", 1, "{"); - testValue("if (){}"); - testSelection(0, 6); - - exec("insertstring", 1, "}"); - testValue("if (){}"); - testSelection(0, 7); - - exec("gotolinestart", 1); - exec("insertstring", 1, "("); - testValue("(if (){}"); - exec("backspace", 1); - - editor.setValue(""); - exec("insertstring", 1, "{"); - assert.equal(editor.getValue(), "{"); - exec("insertstring", 1, "\n"); - assert.equal(editor.getValue(), "{\n \n}"); - - editor.setValue(""); - exec("insertstring", 1, "("); - exec("insertstring", 1, '"'); - exec("insertstring", 1, '"'); - assert.equal(editor.getValue(), '("")'); - 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(["", - " " - ].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), " "); - } -}; - -}); - -if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec(); -} diff --git a/lib/ace/mode/behaviour/cstyle.js b/lib/ace/mode/behaviour/cstyle.js index dd1b0d14..54f75526 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -41,53 +41,98 @@ var SAFE_INSERT_IN_TOKENS = var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; -var context; -var contextCache = {}; -var initContext = function(editor) { - var id = -1; - if (editor.multiSelect) { - id = editor.selection.index; - if (contextCache.rangeCount != editor.multiSelect.rangeCount) - contextCache = {rangeCount: editor.multiSelect.rangeCount}; - } - if (contextCache[id]) - return context = contextCache[id]; - context = contextCache[id] = { - autoInsertedBrackets: 0, - autoInsertedRow: -1, - autoInsertedLineEnd: "", - maybeInsertedBrackets: 0, - maybeInsertedRow: -1, - maybeInsertedLineStart: "", - maybeInsertedLineEnd: "" - }; -}; -var 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 autoInsertedBrackets = 0; +var autoInsertedRow = -1; +var autoInsertedLineEnd = ""; +var maybeInsertedBrackets = 0; +var maybeInsertedRow = -1; +var maybeInsertedLineStart = ""; +var maybeInsertedLineEnd = ""; -var CstyleBehaviour = function() { - this.add("braces", "insertion", function(state, action, editor, session, text) { +var CstyleBehaviour = function () { + + CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + + // Don't insert in the middle of a keyword/identifier/lexical + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + // Look ahead in case we're at the end of a token + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + + // Only insert in front of whitespace/comments + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); + }; + + CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; + }; + + CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + // Reset previous state if text or context changed too much + if (!this.isAutoInsertedClosing(cursor, line, autoInsertedLineEnd[0])) + autoInsertedBrackets = 0; + autoInsertedRow = cursor.row; + autoInsertedLineEnd = bracket + line.substr(cursor.column); + autoInsertedBrackets++; + }; + + CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + maybeInsertedBrackets = 0; + maybeInsertedRow = cursor.row; + maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + maybeInsertedLineEnd = line.substr(cursor.column); + maybeInsertedBrackets++; + }; + + CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return autoInsertedBrackets > 0 && + cursor.row === autoInsertedRow && + bracket === autoInsertedLineEnd[0] && + line.substr(cursor.column) === autoInsertedLineEnd; + }; + + CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return maybeInsertedBrackets > 0 && + cursor.row === maybeInsertedRow && + line.substr(cursor.column) === maybeInsertedLineEnd && + line.substr(0, cursor.column) == maybeInsertedLineStart; + }; + + CstyleBehaviour.popAutoInsertedClosing = function() { + autoInsertedLineEnd = autoInsertedLineEnd.substr(1); + autoInsertedBrackets--; + }; + + CstyleBehaviour.clearMaybeInsertedClosing = function() { + maybeInsertedBrackets = 0; + maybeInsertedRow = -1; + }; + + this.add("braces", "insertion", function (state, action, editor, session, text) { var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); if (text == '{') { - initContext(editor); var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, '{', '}'); + return { + text: '{' + selected + '}', + selection: false + }; } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { - if (/[\]\}\)]/.test(line[cursor.column]) || editor.inMultiSelectMode) { + if (/[\]\}\)]/.test(line[cursor.column])) { CstyleBehaviour.recordAutoInsert(editor, session, "}"); return { text: '{}', @@ -102,7 +147,6 @@ var CstyleBehaviour = function() { } } } else if (text == '}') { - initContext(editor); var rightChar = line.substring(cursor.column, cursor.column + 1); if (rightChar == '}') { var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); @@ -115,57 +159,51 @@ var CstyleBehaviour = function() { } } } else if (text == "\n" || text == "\r\n") { - initContext(editor); var closing = ""; if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { - closing = lang.stringRepeat("}", context.maybeInsertedBrackets); + closing = lang.stringRepeat("}", maybeInsertedBrackets); CstyleBehaviour.clearMaybeInsertedClosing(); } var rightChar = line.substring(cursor.column, cursor.column + 1); - if (rightChar === '}') { - var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column+1}, '}'); + if (rightChar == '}' || closing !== "") { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column}, '}'); if (!openBracePos) return null; - var next_indent = this.$getIndent(session.getLine(openBracePos.row)); - } else if (closing) { - var next_indent = this.$getIndent(line); - } else { - CstyleBehaviour.clearMaybeInsertedClosing(); - return; - } - var indent = next_indent + session.getTabString(); - return { - text: '\n' + indent + '\n' + next_indent + closing, - selection: [1, indent.length, 1, indent.length] - }; - } else { - CstyleBehaviour.clearMaybeInsertedClosing(); + var indent = this.getNextLineIndent(state, line.substring(0, cursor.column), session.getTabString()); + var next_indent = this.$getIndent(line); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } } }); - this.add("braces", "deletion", function(state, action, editor, session, range) { + this.add("braces", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '{') { - initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.end.column, range.end.column + 1); if (rightChar == '}') { range.end.column++; return range; } else { - context.maybeInsertedBrackets--; + maybeInsertedBrackets--; } } }); - this.add("parens", "insertion", function(state, action, editor, session, text) { + this.add("parens", "insertion", function (state, action, editor, session, text) { if (text == '(') { - initContext(editor); var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, '(', ')'); + return { + text: '(' + selected + ')', + selection: false + }; } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { CstyleBehaviour.recordAutoInsert(editor, session, ")"); return { @@ -174,7 +212,6 @@ var CstyleBehaviour = function() { }; } } else if (text == ')') { - initContext(editor); var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var rightChar = line.substring(cursor.column, cursor.column + 1); @@ -191,10 +228,9 @@ var CstyleBehaviour = function() { } }); - this.add("parens", "deletion", function(state, action, editor, session, range) { + this.add("parens", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '(') { - initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == ')') { @@ -204,13 +240,15 @@ var CstyleBehaviour = function() { } }); - this.add("brackets", "insertion", function(state, action, editor, session, text) { + this.add("brackets", "insertion", function (state, action, editor, session, text) { if (text == '[') { - initContext(editor); var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, '[', ']'); + return { + text: '[' + selected + ']', + selection: false + }; } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { CstyleBehaviour.recordAutoInsert(editor, session, "]"); return { @@ -219,7 +257,6 @@ var CstyleBehaviour = function() { }; } } else if (text == ']') { - initContext(editor); var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var rightChar = line.substring(cursor.column, cursor.column + 1); @@ -236,10 +273,9 @@ var CstyleBehaviour = function() { } }); - this.add("brackets", "deletion", function(state, action, editor, session, range) { + this.add("brackets", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && selected == '[') { - initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == ']') { @@ -249,60 +285,69 @@ var CstyleBehaviour = function() { } }); - this.add("string_dquotes", "insertion", function(state, action, editor, session, text) { + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { if (text == '"' || text == "'") { - initContext(editor); var quote = text; var selection = editor.getSelectionRange(); var selected = session.doc.getTextRange(selection); if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { - return getWrapped(selection, selected, quote, quote); - } else if (!selected) { + return { + text: quote + selected + quote, + selection: false + }; + } else { var cursor = editor.getCursorPosition(); var line = session.doc.getLine(cursor.row); var leftChar = line.substring(cursor.column-1, cursor.column); - var rightChar = line.substring(cursor.column, cursor.column + 1); - - var token = session.getTokenAt(cursor.row, cursor.column); - var rightToken = session.getTokenAt(cursor.row, cursor.column + 1); + // We're escaped. - if (leftChar == "\\" && token && /escape/.test(token.type)) + if (leftChar == '\\') { return null; - - var stringBefore = token && /string|escape/.test(token.type); - var stringAfter = !rightToken || /string|escape/.test(rightToken.type); - - var pair; - if (rightChar == quote) { - pair = stringBefore !== stringAfter; - } else { - if (stringBefore && !stringAfter) - return null; // wrap string with different quote - if (stringBefore && stringAfter) - return null; // do not pair quotes inside strings - var wordRe = session.$mode.tokenRe; - wordRe.lastIndex = 0; - var isWordBefore = wordRe.test(leftChar); - wordRe.lastIndex = 0; - var isWordAfter = wordRe.test(leftChar); - if (isWordBefore || isWordAfter) - return null; // before or after alphanumeric - if (rightChar && !/[\s;,.})\]\\]/.test(rightChar)) - return null; // there is rightChar and it isn't closing - pair = true; } - return { - text: pair ? quote + quote : "", - selection: [1,1] - }; + + // Find what token we're inside. + var tokens = session.getTokens(selection.start.row); + var col = 0, token; + var quotepos = -1; // Track whether we're inside an open quote. + + for (var x = 0; x < tokens.length; x++) { + token = tokens[x]; + if (token.type == "string") { + quotepos = -1; + } else if (quotepos < 0) { + quotepos = token.value.indexOf(quote); + } + if ((token.value.length + col) > selection.start.column) { + break; + } + col += tokens[x].value.length; + } + + // Try and be smart about when we auto insert. + if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { + if (!CstyleBehaviour.isSaneInsertion(editor, session)) + return; + return { + text: quote + quote, + selection: [1,1] + }; + } else if (token && token.type === "string") { + // Ignore input and move right one if we're typing over the closing quote. + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == quote) { + return { + text: '', + selection: [1, 1] + }; + } + } } } }); - this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { + this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { var selected = session.doc.getTextRange(range); if (!range.isMultiLine() && (selected == '"' || selected == "'")) { - initContext(editor); var line = session.doc.getLine(range.start.row); var rightChar = line.substring(range.start.column + 1, range.start.column + 2); if (rightChar == selected) { @@ -314,79 +359,6 @@ var CstyleBehaviour = function() { }; - -CstyleBehaviour.isSaneInsertion = function(editor, session) { - var cursor = editor.getCursorPosition(); - var iterator = new TokenIterator(session, cursor.row, cursor.column); - - // Don't insert in the middle of a keyword/identifier/lexical - if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { - // Look ahead in case we're at the end of a token - var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); - if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) - return false; - } - - // Only insert in front of whitespace/comments - iterator.stepForward(); - return iterator.getCurrentTokenRow() !== cursor.row || - this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); -}; - -CstyleBehaviour.$matchTokenType = function(token, types) { - return types.indexOf(token.type || token) > -1; -}; - -CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - // Reset previous state if text or context changed too much - if (!this.isAutoInsertedClosing(cursor, line, context.autoInsertedLineEnd[0])) - context.autoInsertedBrackets = 0; - context.autoInsertedRow = cursor.row; - context.autoInsertedLineEnd = bracket + line.substr(cursor.column); - context.autoInsertedBrackets++; -}; - -CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - if (!this.isMaybeInsertedClosing(cursor, line)) - context.maybeInsertedBrackets = 0; - context.maybeInsertedRow = cursor.row; - context.maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; - context.maybeInsertedLineEnd = line.substr(cursor.column); - context.maybeInsertedBrackets++; -}; - -CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { - return context.autoInsertedBrackets > 0 && - cursor.row === context.autoInsertedRow && - bracket === context.autoInsertedLineEnd[0] && - line.substr(cursor.column) === context.autoInsertedLineEnd; -}; - -CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { - return context.maybeInsertedBrackets > 0 && - cursor.row === context.maybeInsertedRow && - line.substr(cursor.column) === context.maybeInsertedLineEnd && - line.substr(0, cursor.column) == context.maybeInsertedLineStart; -}; - -CstyleBehaviour.popAutoInsertedClosing = function() { - context.autoInsertedLineEnd = context.autoInsertedLineEnd.substr(1); - context.autoInsertedBrackets--; -}; - -CstyleBehaviour.clearMaybeInsertedClosing = function() { - if (context) { - context.maybeInsertedBrackets = 0; - context.maybeInsertedRow = -1; - } -}; - - - oop.inherits(CstyleBehaviour, Behaviour); exports.CstyleBehaviour = CstyleBehaviour; diff --git a/lib/ace/mode/behaviour/html.js b/lib/ace/mode/behaviour/html.js index 181655c0..1d500e0f 100644 --- a/lib/ace/mode/behaviour/html.js +++ b/lib/ace/mode/behaviour/html.js @@ -33,13 +33,55 @@ define(function(require, exports, module) { var oop = require("../../lib/oop"); var XmlBehaviour = require("../behaviour/xml").XmlBehaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var voidElements = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; + +function hasType(token, type) { + var tokenTypes = token.type.split('.'); + return type.split('.').every(function(type){ + return (tokenTypes.indexOf(type) !== -1); + }); + return hasType; +} var HtmlBehaviour = function () { - XmlBehaviour.call(this); - -}; + this.inherit(XmlBehaviour); // Get xml behaviour + + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { + if (text == '>') { + var position = editor.getCursorPosition(); + var iterator = new TokenIterator(session, position.row, position.column); + var token = iterator.getCurrentToken(); + if (token && hasType(token, 'string') && iterator.getCurrentTokenColumn() + token.value.length > position.column) + return; + var atCursor = false; + if (!token || !hasType(token, 'meta.tag') && !(hasType(token, 'text') && token.value.match('/'))){ + do { + token = iterator.stepBackward(); + } while (token && (hasType(token, 'string') || hasType(token, 'keyword.operator') || hasType(token, 'entity.attribute-name') || hasType(token, 'text'))); + } else { + atCursor = true; + } + if (!token || !hasType(token, 'meta.tag.name') || iterator.stepBackward().value.match('/')) { + return; + } + var element = token.value; + if (atCursor){ + var element = element.substring(0, position.column - token.start); + } + if (voidElements.indexOf(element) !== -1){ + return; + } + return { + text: '>' + '', + selection: [1, 1] + } + } + }); +} oop.inherits(HtmlBehaviour, XmlBehaviour); exports.HtmlBehaviour = HtmlBehaviour; diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js index 068fdb31..47261306 100644 --- a/lib/ace/mode/behaviour/xml.js +++ b/lib/ace/mode/behaviour/xml.js @@ -3,7 +3,7 @@ * * 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 @@ -14,7 +14,7 @@ * * 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 @@ -33,171 +33,70 @@ define(function(require, exports, module) { var oop = require("../../lib/oop"); var Behaviour = require("../behaviour").Behaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; var TokenIterator = require("../../token_iterator").TokenIterator; -var lang = require("../../lib/lang"); -function is(token, type) { - return token.type.lastIndexOf(type + ".xml") > -1; +function hasType(token, type) { + var tokenTypes = token.type.split('.'); + return type.split('.').every(function(type){ + return (tokenTypes.indexOf(type) !== -1); + }); + return hasType; } var XmlBehaviour = function () { - - this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { - if (text == '"' || text == "'") { - var quote = text; - var selected = session.doc.getTextRange(editor.getSelectionRange()); - if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { - return { - text: quote + selected + quote, - selection: false - }; - } - - var cursor = editor.getCursorPosition(); - var line = session.doc.getLine(cursor.row); - var rightChar = line.substring(cursor.column, cursor.column + 1); - var iterator = new TokenIterator(session, cursor.row, cursor.column); - var token = iterator.getCurrentToken(); - - if (rightChar == quote && (is(token, "attribute-value") || is(token, "string"))) { - // Ignore input and move right one if we're typing over the closing quote. - return { - text: "", - selection: [1, 1] - }; - } - - if (!token) - token = iterator.stepBackward(); - - if (!token) - return; - - while (is(token, "tag-whitespace") || is(token, "whitespace")) { - token = iterator.stepBackward(); - } - var rightSpace = !rightChar || rightChar.match(/\s/); - if (is(token, "attribute-equals") && (rightSpace || rightChar == '>') || (is(token, "decl-attribute-equals") && (rightSpace || rightChar == '?'))) { - return { - text: quote + quote, - selection: [1, 1] - }; - } - } - }); - - this.add("string_dquotes", "deletion", function(state, action, editor, session, range) { - var selected = session.doc.getTextRange(range); - if (!range.isMultiLine() && (selected == '"' || selected == "'")) { - var line = session.doc.getLine(range.start.row); - var rightChar = line.substring(range.start.column + 1, range.start.column + 2); - if (rightChar == selected) { - range.end.column++; - return range; - } - } - }); - + + this.inherit(CstyleBehaviour, ["string_dquotes"]); // Get string behaviour + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { if (text == '>') { var position = editor.getCursorPosition(); var iterator = new TokenIterator(session, position.row, position.column); - var token = iterator.getCurrentToken() || iterator.stepBackward(); + var token = iterator.getCurrentToken(); - // exit if we're not in a tag - if (!token || !(is(token, "tag-name") || is(token, "tag-whitespace") || is(token, "attribute-name") || is(token, "attribute-equals") || is(token, "attribute-value"))) + if (token && hasType(token, 'string') && iterator.getCurrentTokenColumn() + token.value.length > position.column) return; - - // exit if we're inside of a quoted attribute value - if (is(token, "reference.attribute-value")) - return; - if (is(token, "attribute-value")) { - var firstChar = token.value.charAt(0); - if (firstChar == '"' || firstChar == "'") { - var lastChar = token.value.charAt(token.value.length - 1); - var tokenEnd = iterator.getCurrentTokenColumn() + token.value.length; - if (tokenEnd > position.column || tokenEnd == position.column && firstChar != lastChar) - return; - } + var atCursor = false; + if (!token || !hasType(token, 'meta.tag') && !(hasType(token, 'text') && token.value.match('/'))){ + do { + token = iterator.stepBackward(); + } while (token && (hasType(token, 'string') || hasType(token, 'keyword.operator') || hasType(token, 'entity.attribute-name') || hasType(token, 'text'))); + } else { + atCursor = true; } - - // find tag name - while (!is(token, "tag-name")) { - token = iterator.stepBackward(); - } - - var tokenRow = iterator.getCurrentTokenRow(); - var tokenColumn = iterator.getCurrentTokenColumn(); - - // exit if the tag is ending - if (is(iterator.stepBackward(), "end-tag-open")) + if (!token || !hasType(token, 'meta.tag.name') || iterator.stepBackward().value.match('/')) { return; - - var element = token.value; - if (tokenRow == position.row) - element = element.substring(0, position.column - tokenColumn); - - if (this.voidElements.hasOwnProperty(element.toLowerCase())) - return; + } + var tag = token.value; + if (atCursor){ + var tag = tag.substring(0, position.column - token.start); + } return { - text: ">" + "", + text: '>' + '', selection: [1, 1] - }; + } } }); - this.add("autoindent", "insertion", function (state, action, editor, session, text) { + this.add('autoindent', 'insertion', function (state, action, editor, session, text) { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var iterator = new TokenIterator(session, cursor.row, cursor.column); - var token = iterator.getCurrentToken(); + var rightChars = line.substring(cursor.column, cursor.column + 2); + if (rightChars == '") - return; - //get tag name - while (token && token.type.indexOf("tag-name") === -1) { - token = iterator.stepBackward(); - } - - if (!token) { - return; - } - - var tag = token.value; - var row = iterator.getCurrentTokenRow(); - - //don't indent after closing tag - token = iterator.stepBackward(); - if (!token || token.type.indexOf("end-tag") !== -1) { - return; - } - - if (this.voidElements && !this.voidElements[tag]) { - var nextToken = session.getTokenAt(cursor.row, cursor.column+1); - var line = session.getLine(row); - var nextIndent = this.$getIndent(line); - var indent = nextIndent + session.getTabString(); - - if (nextToken && nextToken.value === " the first match is used - this.$rules = { + this.$rules = { "start" : [ { token : "comment", - regex : "//", - next : "singleLineComment" + regex : "\\/\\/.*$" }, DocCommentHighlightRules.getStartRule("doc-start"), { @@ -84,11 +82,11 @@ var c_cppHighlightRules = function() { regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?(L|l|UL|ul|u|U|F|f|ll|LL|ull|ULL)?\\b" }, { token : "keyword", // pre-compiler directives - regex : "#\\s*(?:include|import|pragma|line|define|undef)\\b", + regex : "#\\s*(?:include|import|pragma|line|define|undef|if|ifdef|else|elif|ifndef)\\b", next : "directive" }, { token : "keyword", // special case pre-compiler directive - regex : "#\\s*(?:endif|if|ifdef|else|elif|ifndef)\\b" + regex : "(?:#\\s*endif)\\b" }, { token : "support.function.C99.c", regex : cFunctions @@ -122,26 +120,14 @@ var c_cppHighlightRules = function() { regex : ".+" } ], - "singleLineComment" : [ - { - token : "comment", - regex : /\\$/, - next : "singleLineComment" - }, { - token : "comment", - regex : /$/, - next : "start" - }, { - defaultToken: "comment" - } - ], "qqstring" : [ { token : "string", regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', next : "start" }, { - defaultToken : "string" + token : "string", + regex : '.+' } ], "qstring" : [ @@ -150,7 +136,8 @@ var c_cppHighlightRules = function() { regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", next : "start" }, { - defaultToken : "string" + token : "string", + regex : '.+' } ], "directive" : [ diff --git a/lib/ace/mode/cirru.js b/lib/ace/mode/cirru.js deleted file mode 100644 index 5f1c4d9e..00000000 --- a/lib/ace/mode/cirru.js +++ /dev/null @@ -1,51 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2014, 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 CirruHighlightRules = require("./cirru_highlight_rules").CirruHighlightRules; -var CoffeeFoldMode = require("./folding/coffee").FoldMode; - -var Mode = function() { - this.HighlightRules = CirruHighlightRules; - this.foldingRules = new CoffeeFoldMode(); -}; -oop.inherits(Mode, TextMode); - -(function() { - this.lineCommentStart = "--"; - this.$id = "ace/mode/cirru"; -}).call(Mode.prototype); - -exports.Mode = Mode; -}); diff --git a/lib/ace/mode/cirru_highlight_rules.js b/lib/ace/mode/cirru_highlight_rules.js deleted file mode 100644 index 737ec0be..00000000 --- a/lib/ace/mode/cirru_highlight_rules.js +++ /dev/null @@ -1,125 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2014, 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 TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; - -// see http://cirru.org for more about this language -var CirruHighlightRules = function() { - this.$rules = { - start: [{ - token: 'constant.numeric', - regex: /[\d\.]+/ - }, { - token: 'comment.line.double-dash', - regex: /--/, - next: 'comment', - }, { - token: 'storage.modifier', - regex: /\(/, - }, { - token: 'storage.modifier', - regex: /\,/, - next: 'line', - }, { - token: 'support.function', - regex: /[^\(\)\"\s]+/, - next: 'line' - }, { - token: 'string.quoted.double', - regex: /"/, - next: 'string', - }, { - token: 'storage.modifier', - regex: /\)/, - }], - comment: [{ - token: 'comment.line.double-dash', - regex: /\ +[^\n]+/, - next: 'start', - }], - string: [{ - token: 'string.quoted.double', - regex: /"/, - next: 'line', - }, { - token: 'constant.character.escape', - regex: /\\/, - next: 'escape', - }, { - token: 'string.quoted.double', - regex: /[^\\\"]+/, - }], - escape: [{ - token: 'constant.character.escape', - regex: /./, - next: 'string', - }], - line: [{ - token: 'constant.numeric', - regex: /[\d\.]+/ - }, { - token: 'markup.raw', - regex: /^\s*/, - next: 'start', - }, { - token: 'storage.modifier', - regex: /\$/, - next: 'start', - }, { - token: 'variable.parameter', - regex: /[^\(\)\"\s]+/ - }, { - token: 'storage.modifier', - regex: /\(/, - next: 'start' - }, { - token: 'storage.modifier', - regex: /\)/, - }, { - token: 'markup.raw', - regex: /^\ */, - next: 'start', - }, { - token: 'string.quoted.double', - regex: /"/, - next: 'string', - }] - } - -}; - -oop.inherits(CirruHighlightRules, TextHighlightRules); - -exports.CirruHighlightRules = CirruHighlightRules; -}); diff --git a/lib/ace/mode/clojure.js b/lib/ace/mode/clojure.js index ee44ac3e..df67dc06 100644 --- a/lib/ace/mode/clojure.js +++ b/lib/ace/mode/clojure.js @@ -3,7 +3,7 @@ * * 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 @@ -14,7 +14,7 @@ * * 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 @@ -33,11 +33,15 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var ClojureHighlightRules = require("./clojure_highlight_rules").ClojureHighlightRules; var MatchingParensOutdent = require("./matching_parens_outdent").MatchingParensOutdent; +var Range = require("../range").Range; var Mode = function() { - this.HighlightRules = ClojureHighlightRules; + var highlighter = new ClojureHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$keywordList = highlighter.$keywordList; this.$outdent = new MatchingParensOutdent(); }; oop.inherits(Mode, TextMode); @@ -45,72 +49,29 @@ oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = ";"; - this.minorIndentFunctions = ["defn", "defn-", "defmacro", "def", "deftest", "testing"]; - - this.$toIndent = function(str) { - return str.split('').map(function(ch) { - if (/\s/.exec(ch)) { - return ch; - } else { - return ' '; - } - }).join(''); - }; - - this.$calculateIndent = function(line, tab) { - var baseIndent = this.$getIndent(line); - var delta = 0; - var isParen, ch; - // Walk back from end of line, find matching braces - for (var i = line.length - 1; i >= 0; i--) { - ch = line[i]; - if (ch === '(') { - delta--; - isParen = true; - } else if (ch === '(' || ch === '[' || ch === '{') { - delta--; - isParen = false; - } else if (ch === ')' || ch === ']' || ch === '}') { - delta++; - } - if (delta < 0) { - break; - } - } - if (delta < 0 && isParen) { - // Were more brackets opened than closed and was a ( left open? - i += 1; - var iBefore = i; - var fn = ''; - while (true) { - ch = line[i]; - if (ch === ' ' || ch === '\t') { - if(this.minorIndentFunctions.indexOf(fn) !== -1) { - return this.$toIndent(line.substring(0, iBefore - 1) + tab); - } else { - return this.$toIndent(line.substring(0, i + 1)); - } - } else if (ch === undefined) { - return this.$toIndent(line.substring(0, iBefore - 1) + tab); - } - fn += line[i]; - i++; - } - } else if(delta < 0 && !isParen) { - // Were more brackets openend than closed and was it not a (? - return this.$toIndent(line.substring(0, i+1)); - } else if(delta > 0) { - // Mere more brackets closed than opened? Outdent. - baseIndent = baseIndent.substring(0, baseIndent.length - tab.length); - return baseIndent; - } else { - // Were they nicely matched? Just indent like line before. - return baseIndent; - } - }; this.getNextLineIndent = function(state, line, tab) { - return this.$calculateIndent(line, tab); + var indent = this.$getIndent(line); + + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/[\(\[]/); + if (match) { + indent += " "; + } + match = line.match(/[\)]/); + if (match) { + indent = ""; + } + } + + return indent; }; this.checkOutdent = function(state, line, input) { @@ -121,7 +82,6 @@ oop.inherits(Mode, TextMode); this.$outdent.autoOutdent(doc, row); }; - this.$id = "ace/mode/clojure"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/cobol.js b/lib/ace/mode/cobol.js index 91713bd0..4ff2f7ef 100644 --- a/lib/ace/mode/cobol.js +++ b/lib/ace/mode/cobol.js @@ -33,11 +33,12 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var CobolHighlightRules = require("./cobol_highlight_rules").CobolHighlightRules; var Range = require("../range").Range; var Mode = function() { - this.HighlightRules = CobolHighlightRules; + this.$tokenizer = new Tokenizer(new CobolHighlightRules().getRules()); }; oop.inherits(Mode, TextMode); @@ -45,7 +46,6 @@ oop.inherits(Mode, TextMode); this.lineCommentStart = "*"; - this.$id = "ace/mode/cobol"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/coffee.js b/lib/ace/mode/coffee.js index e866f2b0..4a6d2201 100644 --- a/lib/ace/mode/coffee.js +++ b/lib/ace/mode/coffee.js @@ -31,6 +31,7 @@ define(function(require, exports, module) { "use strict"; +var Tokenizer = require("../tokenizer").Tokenizer; var Rules = require("./coffee_highlight_rules").CoffeeHighlightRules; var Outdent = require("./matching_brace_outdent").MatchingBraceOutdent; var FoldMode = require("./folding/coffee").FoldMode; @@ -40,8 +41,10 @@ var WorkerClient = require("../worker/worker_client").WorkerClient; var oop = require("../lib/oop"); function Mode() { - this.HighlightRules = Rules; + var highlighter = new Rules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); this.$outdent = new Outdent(); + this.$keywordList = highlighter.$keywordList; this.foldingRules = new FoldMode(); } @@ -49,35 +52,14 @@ oop.inherits(Mode, TextMode); (function() { - /*: - [({[=:] # Opening parentheses or brackets - |[-=]> # OR single or double arrow - |\b(?: # OR one of these words: - else # else - |try # OR try - |(?:swi|ca)tch # OR catch, optionally followed by: - (?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)? # a variable - |finally # OR finally - ))\s*$ # all as the last thing on a line (allowing trailing space) - | # ---- OR ---- : - ^\s* # a line starting with optional space - (else\b\s*)? # followed by an optional "else" - (?: # followed by one of the following: - if # if - |for # OR for - |while # OR while - |loop # OR loop - )\b # (as a word) - (?!.*\bthen\b) # ... but NOT followed by "then" on the line - */ - var indenter = /(?:[({[=:]|[-=]>|\b(?:else|try|(?:swi|ca)tch(?:\s+[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$|^\s*(else\b\s*)?(?:if|for|while|loop)\b(?!.*\bthen\b)/; + var indenter = /(?:[({[=:]|[-=]>|\b(?:else|switch|try|catch(?:\s*[$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)?|finally))\s*$/; var commentLine = /^(\s*)#/; var hereComment = /^\s*###(?!#)/; var indentation = /^\s*/; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); - var tokens = this.getTokenizer().getLineTokens(line, state).tokens; + var tokens = this.$tokenizer.getLineTokens(line, state).tokens; if (!(tokens.length && tokens[tokens.length - 1].type === 'comment') && state === 'start' && indenter.test(line)) @@ -116,18 +98,17 @@ oop.inherits(Mode, TextMode); var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker"); worker.attachToDocument(session.getDocument()); - worker.on("annotate", function(e) { - session.setAnnotations(e.data); + worker.on("error", function(e) { + session.setAnnotations([e.data]); }); - worker.on("terminate", function() { + worker.on("ok", function(e) { session.clearAnnotations(); }); return worker; }; - this.$id = "ace/mode/coffee"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/coffee/helpers.js b/lib/ace/mode/coffee/helpers.js index 60412fc6..fe73f2b7 100644 --- a/lib/ace/mode/coffee/helpers.js +++ b/lib/ace/mode/coffee/helpers.js @@ -194,7 +194,7 @@ define(function(require, exports, module) { pathSep = useWinPathSep ? /\\|\// : /\//; parts = file.split(pathSep); file = parts[parts.length - 1]; - if (!(stripExt && file.indexOf('.') >= 0)) { + if (!stripExt) { return file; } parts = file.split('.'); diff --git a/lib/ace/mode/coffee/lexer.js b/lib/ace/mode/coffee/lexer.js index 05d85236..ed02bfe0 100644 --- a/lib/ace/mode/coffee/lexer.js +++ b/lib/ace/mode/coffee/lexer.js @@ -193,25 +193,30 @@ define(function(require, exports, module) { }; Lexer.prototype.stringToken = function() { - var octalEsc, quote, string, trimmed; - switch (quote = this.chunk.charAt(0)) { + var match, octalEsc, string; + switch (this.chunk.charAt(0)) { case "'": - string = SIMPLESTR.exec(this.chunk)[0]; + if (!(match = SIMPLESTR.exec(this.chunk))) { + return 0; + } + string = match[0]; + this.token('STRING', string.replace(MULTILINER, '\\\n'), 0, string.length); break; case '"': - string = this.balancedString(this.chunk, '"'); - } - if (!string) { - return 0; - } - trimmed = this.removeNewlines(string.slice(1, -1)); - if (quote === '"' && 0 < string.indexOf('#{', 1)) { - this.interpolateString(trimmed, { - strOffset: 1, - lexedLength: string.length - }); - } else { - this.token('STRING', quote + this.escapeLines(trimmed) + quote, 0, string.length); + if (!(string = this.balancedString(this.chunk, '"'))) { + return 0; + } + if (0 < string.indexOf('#{', 1)) { + this.interpolateString(string.slice(1, -1), { + strOffset: 1, + lexedLength: string.length + }); + } else { + this.token('STRING', this.escapeLines(string, 0, string.length)); + } + break; + default: + return 0; } if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) { this.error("octal escape sequences " + string + " are not allowed"); @@ -297,7 +302,7 @@ define(function(require, exports, module) { var body, flags, flagsOffset, heregex, plusToken, prev, re, tag, token, tokens, value, _i, _len, _ref2, _ref3, _ref4; heregex = match[0], body = match[1], flags = match[2]; if (0 > body.indexOf('#{')) { - re = this.escapeLines(body.replace(HEREGEX_OMIT, '$1$2').replace(/\//g, '\\/'), true); + re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/'); if (re.match(/^\*/)) { this.error('regular expressions cannot begin with `*`'); } @@ -316,7 +321,7 @@ define(function(require, exports, module) { if (tag === 'TOKENS') { tokens.push.apply(tokens, value); } else if (tag === 'NEOSTRING') { - if (!(value = value.replace(HEREGEX_OMIT, '$1$2'))) { + if (!(value = value.replace(HEREGEX_OMIT, ''))) { continue; } value = value.replace(/\\/g, '\\\\'); @@ -623,6 +628,10 @@ define(function(require, exports, module) { offsetInChunk = offsetInChunk || 0; strOffset = strOffset || 0; lexedLength = lexedLength || str.length; + if (heredoc && str.length > 0 && str[0] === '\n') { + str = str.slice(1); + strOffset++; + } tokens = []; pi = 0; i = -1; @@ -780,31 +789,16 @@ define(function(require, exports, module) { return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS'); }; - Lexer.prototype.removeNewlines = function(str) { - return str.replace(/^\s*\n\s*/, '').replace(/([^\\]|\\\\)\s*\n\s*$/, '$1'); - }; - Lexer.prototype.escapeLines = function(str, heredoc) { - str = str.replace(/\\[^\S\n]*(\n|\\)\s*/g, function(escaped, character) { - if (character === '\n') { - return ''; - } else { - return escaped; - } - }); - if (heredoc) { - return str.replace(MULTILINER, '\\n'); - } else { - return str.replace(/\s*\n\s*/g, ' '); - } + return str.replace(MULTILINER, heredoc ? '\\n' : ''); }; Lexer.prototype.makeString = function(body, quote, heredoc) { if (!body) { return quote + quote; } - body = body.replace(RegExp("\\\\(" + quote + "|\\\\)", "g"), function(match, contents) { - if (contents === quote) { + body = body.replace(/\\([\s\S])/g, function(match, contents) { + if (contents === '\n' || contents === quote) { return contents; } else { return match; @@ -873,27 +867,27 @@ define(function(require, exports, module) { NUMBER = /^0b[01]+|^0o[0-7]+|^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i; - HEREDOC = /^("""|''')((?:\\[\s\S]|[^\\])*?)(?:\n[^\n\S]*)?\1/; + HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/; OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?(\.|::)|\.{2,3})/; WHITESPACE = /^[^\n\S]+/; - COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|###$)|^(?:\s*#(?!##[^#]).*)+/; + COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)$)|^(?:\s*#(?!##[^#]).*)+/; CODE = /^[-=]>/; MULTI_DENT = /^(?:\n[^\n\S]*)+/; - SIMPLESTR = /^'[^\\']*(?:\\[\s\S][^\\']*)*'/; + SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/; JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/; REGEX = /^(\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/)([imgy]{0,4})(?!\w)/; - HEREGEX = /^\/{3}((?:\\?[\s\S])+?)\/{3}([imgy]{0,4})(?!\w)/; + HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/; - HEREGEX_OMIT = /((?:\\\\)+)|\\(\s|\/)|\s+(?:#.*)?/g; + HEREGEX_OMIT = /\s+(?:#.*)?/g; MULTILINER = /\n/g; diff --git a/lib/ace/mode/coffee/nodes.js b/lib/ace/mode/coffee/nodes.js index 52afdf2c..b97dd58a 100644 --- a/lib/ace/mode/coffee/nodes.js +++ b/lib/ace/mode/coffee/nodes.js @@ -27,7 +27,7 @@ define(function(require, exports, module) { // Generated by CoffeeScript 1.6.3 - var Access, Arr, Assign, Base, Block, Call, Class, Code, CodeFragment, Comment, Existence, Extends, For, HEXNUM, IDENTIFIER, IDENTIFIER_STR, IS_REGEX, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, NUMBER, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, isLiteralArguments, isLiteralThis, last, locationDataToString, merge, multident, parseNum, some, starts, throwSyntaxError, unfoldSoak, utility, _ref, _ref1, + var Access, Arr, Assign, Base, Block, Call, Class, Closure, Code, CodeFragment, Comment, Existence, Extends, For, IDENTIFIER, IDENTIFIER_STR, IS_STRING, If, In, Index, LEVEL_ACCESS, LEVEL_COND, LEVEL_LIST, LEVEL_OP, LEVEL_PAREN, LEVEL_TOP, Literal, METHOD_DEF, NEGATE, NO, Obj, Op, Param, Parens, RESERVED, Range, Return, SIMPLENUM, STRICT_PROSCRIBED, Scope, Slice, Splat, Switch, TAB, THIS, Throw, Try, UTILITIES, Value, While, YES, addLocationDataFn, compact, del, ends, extend, flatten, fragmentsToText, last, locationDataToString, merge, multident, some, starts, throwSyntaxError, unfoldSoak, utility, _ref, _ref1, _ref2, _ref3, __hasProp = {}.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, @@ -114,24 +114,12 @@ define(function(require, exports, module) { }; Base.prototype.compileClosure = function(o) { - var args, argumentsNode, func, jumpNode, meth; + var jumpNode; if (jumpNode = this.jumps()) { jumpNode.error('cannot use a pure statement in an expression'); } o.sharedScope = true; - func = new Code([], Block.wrap([this])); - args = []; - if ((argumentsNode = this.contains(isLiteralArguments)) || this.contains(isLiteralThis)) { - args = [new Literal('this')]; - if (argumentsNode) { - meth = 'apply'; - args.push(new Literal('arguments')); - } else { - meth = 'call'; - } - func = new Value(func, [new Access(new Literal(meth))]); - } - return (new Call(func, args)).compileNode(o); + return Closure.wrap(this).compileNode(o); }; Base.prototype.cache = function(o, level, reused) { @@ -354,12 +342,12 @@ define(function(require, exports, module) { }; Block.prototype.jumps = function(o) { - var exp, jumpNode, _i, _len, _ref2; + var exp, _i, _len, _ref2; _ref2 = this.expressions; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { exp = _ref2[_i]; - if (jumpNode = exp.jumps(o)) { - return jumpNode; + if (exp.jumps(o)) { + return exp; } } }; @@ -594,7 +582,8 @@ define(function(require, exports, module) { __extends(Undefined, _super); function Undefined() { - return Undefined.__super__.constructor.apply(this, arguments); + _ref2 = Undefined.__super__.constructor.apply(this, arguments); + return _ref2; } Undefined.prototype.isAssignable = NO; @@ -613,7 +602,8 @@ define(function(require, exports, module) { __extends(Null, _super); function Null() { - return Null.__super__.constructor.apply(this, arguments); + _ref3 = Null.__super__.constructor.apply(this, arguments); + return _ref3; } Null.prototype.isAssignable = NO; @@ -665,8 +655,8 @@ define(function(require, exports, module) { Return.prototype.jumps = THIS; Return.prototype.compileToFragments = function(o, level) { - var expr, _ref2; - expr = (_ref2 = this.expression) != null ? _ref2.makeReturn() : void 0; + var expr, _ref4; + expr = (_ref4 = this.expression) != null ? _ref4.makeReturn() : void 0; if (expr && !(expr instanceof Return)) { return expr.compileToFragments(o, level); } else { @@ -715,16 +705,8 @@ define(function(require, exports, module) { return !!this.properties.length; }; - Value.prototype.bareLiteral = function(type) { - return !this.properties.length && this.base instanceof type; - }; - Value.prototype.isArray = function() { - return this.bareLiteral(Arr); - }; - - Value.prototype.isRange = function() { - return this.bareLiteral(Range); + return !this.properties.length && this.base instanceof Arr; }; Value.prototype.isComplex = function() { @@ -736,22 +718,18 @@ define(function(require, exports, module) { }; Value.prototype.isSimpleNumber = function() { - return this.bareLiteral(Literal) && SIMPLENUM.test(this.base.value); + return this.base instanceof Literal && SIMPLENUM.test(this.base.value); }; Value.prototype.isString = function() { - return this.bareLiteral(Literal) && IS_STRING.test(this.base.value); - }; - - Value.prototype.isRegex = function() { - return this.bareLiteral(Literal) && IS_REGEX.test(this.base.value); + return this.base instanceof Literal && IS_STRING.test(this.base.value); }; Value.prototype.isAtomic = function() { - var node, _i, _len, _ref2; - _ref2 = this.properties.concat(this.base); - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - node = _ref2[_i]; + var node, _i, _len, _ref4; + _ref4 = this.properties.concat(this.base); + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + node = _ref4[_i]; if (node.soak || node instanceof Call) { return false; } @@ -759,10 +737,6 @@ define(function(require, exports, module) { return true; }; - Value.prototype.isNotCallable = function() { - return this.isSimpleNumber() || this.isString() || this.isRegex() || this.isArray() || this.isRange() || this.isSplice() || this.isObject(); - }; - Value.prototype.isStatement = function(o) { return !this.properties.length && this.base.isStatement(o); }; @@ -786,11 +760,6 @@ define(function(require, exports, module) { return last(this.properties) instanceof Slice; }; - Value.prototype.looksStatic = function(className) { - var _ref2; - return this.base.value === className && this.properties.length && ((_ref2 = this.properties[0].name) != null ? _ref2.value : void 0) !== 'prototype'; - }; - Value.prototype.unwrap = function() { if (this.properties.length) { return this; @@ -837,34 +806,33 @@ define(function(require, exports, module) { }; Value.prototype.unfoldSoak = function(o) { - return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (function(_this) { - return function() { - var fst, i, ifn, prop, ref, snd, _i, _len, _ref2, _ref3; - if (ifn = _this.base.unfoldSoak(o)) { - (_ref2 = ifn.body.properties).push.apply(_ref2, _this.properties); - return ifn; + var _this = this; + return this.unfoldedSoak != null ? this.unfoldedSoak : this.unfoldedSoak = (function() { + var fst, i, ifn, prop, ref, snd, _i, _len, _ref4, _ref5; + if (ifn = _this.base.unfoldSoak(o)) { + (_ref4 = ifn.body.properties).push.apply(_ref4, _this.properties); + return ifn; + } + _ref5 = _this.properties; + for (i = _i = 0, _len = _ref5.length; _i < _len; i = ++_i) { + prop = _ref5[i]; + if (!prop.soak) { + continue; } - _ref3 = _this.properties; - for (i = _i = 0, _len = _ref3.length; _i < _len; i = ++_i) { - prop = _ref3[i]; - if (!prop.soak) { - continue; - } - prop.soak = false; - fst = new Value(_this.base, _this.properties.slice(0, i)); - snd = new Value(_this.base, _this.properties.slice(i)); - if (fst.isComplex()) { - ref = new Literal(o.scope.freeVariable('ref')); - fst = new Parens(new Assign(ref, fst)); - snd.base = ref; - } - return new If(new Existence(fst), snd, { - soak: true - }); + prop.soak = false; + fst = new Value(_this.base, _this.properties.slice(0, i)); + snd = new Value(_this.base, _this.properties.slice(i)); + if (fst.isComplex()) { + ref = new Literal(o.scope.freeVariable('ref')); + fst = new Parens(new Assign(ref, fst)); + snd.base = ref; } - return false; - }; - })(this)(); + return new If(new Existence(fst), snd, { + soak: true + }); + } + return false; + })(); }; return Value; @@ -883,9 +851,8 @@ define(function(require, exports, module) { Comment.prototype.makeReturn = THIS; Comment.prototype.compileNode = function(o, level) { - var code, comment; - comment = this.comment.replace(/^(\s*)#/gm, "$1 *"); - code = "/*" + (multident(comment, this.tab)) + (__indexOf.call(comment, '\n') >= 0 ? "\n" + this.tab : '') + " */"; + var code; + code = "/*" + (multident(this.comment, this.tab)) + (__indexOf.call(this.comment, '\n') >= 0 ? "\n" + this.tab : '') + "*/"; if ((level || o.level) === LEVEL_TOP) { code = o.indent + code; } @@ -905,16 +872,13 @@ define(function(require, exports, module) { this.isNew = false; this.isSuper = variable === 'super'; this.variable = this.isSuper ? null : variable; - if (variable instanceof Value && variable.isNotCallable()) { - variable.error("literal is not a function"); - } } Call.prototype.children = ['variable', 'args']; Call.prototype.newInstance = function() { - var base, _ref2; - base = ((_ref2 = this.variable) != null ? _ref2.base : void 0) || this.variable; + var base, _ref4; + base = ((_ref4 = this.variable) != null ? _ref4.base : void 0) || this.variable; if (base instanceof Call && !base.isNew) { base.newInstance(); } else { @@ -947,13 +911,13 @@ define(function(require, exports, module) { }; Call.prototype.unfoldSoak = function(o) { - var call, ifn, left, list, rite, _i, _len, _ref2, _ref3; + var call, ifn, left, list, rite, _i, _len, _ref4, _ref5; if (this.soak) { if (this.variable) { if (ifn = unfoldSoak(o, this, 'variable')) { return ifn; } - _ref2 = new Value(this.variable).cacheReference(o), left = _ref2[0], rite = _ref2[1]; + _ref4 = new Value(this.variable).cacheReference(o), left = _ref4[0], rite = _ref4[1]; } else { left = new Literal(this.superReference(o)); rite = new Value(left); @@ -981,9 +945,9 @@ define(function(require, exports, module) { break; } } - _ref3 = list.reverse(); - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - call = _ref3[_i]; + _ref5 = list.reverse(); + for (_i = 0, _len = _ref5.length; _i < _len; _i++) { + call = _ref5[_i]; if (ifn) { if (call.variable instanceof Call) { call.variable = ifn; @@ -997,18 +961,18 @@ define(function(require, exports, module) { }; Call.prototype.compileNode = function(o) { - var arg, argIndex, compiledArgs, compiledArray, fragments, preface, _i, _len, _ref2, _ref3; - if ((_ref2 = this.variable) != null) { - _ref2.front = this.front; + var arg, argIndex, compiledArgs, compiledArray, fragments, preface, _i, _len, _ref4, _ref5; + if ((_ref4 = this.variable) != null) { + _ref4.front = this.front; } compiledArray = Splat.compileSplattedArray(o, this.args, true); if (compiledArray.length) { return this.compileSplat(o, compiledArray); } compiledArgs = []; - _ref3 = this.args; - for (argIndex = _i = 0, _len = _ref3.length; _i < _len; argIndex = ++_i) { - arg = _ref3[argIndex]; + _ref5 = this.args; + for (argIndex = _i = 0, _len = _ref5.length; _i < _len; argIndex = ++_i) { + arg = _ref5[argIndex]; if (argIndex) { compiledArgs.push(this.makeCode(", ")); } @@ -1148,23 +1112,23 @@ define(function(require, exports, module) { } Range.prototype.compileVariables = function(o) { - var step, _ref2, _ref3, _ref4, _ref5; + var step, _ref4, _ref5, _ref6, _ref7; o = merge(o, { top: true }); - _ref2 = this.cacheToCodeFragments(this.from.cache(o, LEVEL_LIST)), this.fromC = _ref2[0], this.fromVar = _ref2[1]; - _ref3 = this.cacheToCodeFragments(this.to.cache(o, LEVEL_LIST)), this.toC = _ref3[0], this.toVar = _ref3[1]; + _ref4 = this.cacheToCodeFragments(this.from.cache(o, LEVEL_LIST)), this.fromC = _ref4[0], this.fromVar = _ref4[1]; + _ref5 = this.cacheToCodeFragments(this.to.cache(o, LEVEL_LIST)), this.toC = _ref5[0], this.toVar = _ref5[1]; if (step = del(o, 'step')) { - _ref4 = this.cacheToCodeFragments(step.cache(o, LEVEL_LIST)), this.step = _ref4[0], this.stepVar = _ref4[1]; + _ref6 = this.cacheToCodeFragments(step.cache(o, LEVEL_LIST)), this.step = _ref6[0], this.stepVar = _ref6[1]; } - _ref5 = [this.fromVar.match(NUMBER), this.toVar.match(NUMBER)], this.fromNum = _ref5[0], this.toNum = _ref5[1]; + _ref7 = [this.fromVar.match(SIMPLENUM), this.toVar.match(SIMPLENUM)], this.fromNum = _ref7[0], this.toNum = _ref7[1]; if (this.stepVar) { - return this.stepNum = this.stepVar.match(NUMBER); + return this.stepNum = this.stepVar.match(SIMPLENUM); } }; Range.prototype.compileNode = function(o) { - var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref2, _ref3; + var cond, condPart, from, gt, idx, idxName, known, lt, namedIndex, stepPart, to, varPart, _ref4, _ref5; if (!this.fromVar) { this.compileVariables(o); } @@ -1182,8 +1146,8 @@ define(function(require, exports, module) { if (this.step !== this.stepVar) { varPart += ", " + this.step; } - _ref2 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref2[0], gt = _ref2[1]; - condPart = this.stepNum ? parseNum(this.stepNum[0]) > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref3 = [parseNum(this.fromNum[0]), parseNum(this.toNum[0])], from = _ref3[0], to = _ref3[1], _ref3), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = this.stepVar ? "" + this.stepVar + " > 0" : "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); + _ref4 = ["" + idx + " <" + this.equals, "" + idx + " >" + this.equals], lt = _ref4[0], gt = _ref4[1]; + condPart = this.stepNum ? +this.stepNum > 0 ? "" + lt + " " + this.toVar : "" + gt + " " + this.toVar : known ? ((_ref5 = [+this.fromNum, +this.toNum], from = _ref5[0], to = _ref5[1], _ref5), from <= to ? "" + lt + " " + to : "" + gt + " " + to) : (cond = this.stepVar ? "" + this.stepVar + " > 0" : "" + this.fromVar + " <= " + this.toVar, "" + cond + " ? " + lt + " " + this.toVar + " : " + gt + " " + this.toVar); stepPart = this.stepVar ? "" + idx + " += " + this.stepVar : known ? namedIndex ? from <= to ? "++" + idx : "--" + idx : from <= to ? "" + idx + "++" : "" + idx + "--" : namedIndex ? "" + cond + " ? ++" + idx + " : --" + idx : "" + cond + " ? " + idx + "++ : " + idx + "--"; if (namedIndex) { varPart = "" + idxName + " = " + varPart; @@ -1195,11 +1159,11 @@ define(function(require, exports, module) { }; Range.prototype.compileArray = function(o) { - var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref2, _ref3, _results; + var args, body, cond, hasArgs, i, idt, post, pre, range, result, vars, _i, _ref4, _ref5, _results; if (this.fromNum && this.toNum && Math.abs(this.fromNum - this.toNum) <= 20) { range = (function() { _results = []; - for (var _i = _ref2 = +this.fromNum, _ref3 = +this.toNum; _ref2 <= _ref3 ? _i <= _ref3 : _i >= _ref3; _ref2 <= _ref3 ? _i++ : _i--){ _results.push(_i); } + for (var _i = _ref4 = +this.fromNum, _ref5 = +this.toNum; _ref4 <= _ref5 ? _i <= _ref5 : _i >= _ref5; _ref4 <= _ref5 ? _i++ : _i--){ _results.push(_i); } return _results; }).apply(this); if (this.exclusive) { @@ -1221,7 +1185,9 @@ define(function(require, exports, module) { } post = "{ " + result + ".push(" + i + "); }\n" + idt + "return " + result + ";\n" + o.indent; hasArgs = function(node) { - return node != null ? node.contains(isLiteralArguments) : void 0; + return node != null ? node.contains(function(n) { + return n instanceof Literal && n.value === 'arguments' && !n.asKey; + }) : void 0; }; if (hasArgs(this.from) || hasArgs(this.to)) { args = ', arguments'; @@ -1244,8 +1210,8 @@ define(function(require, exports, module) { } Slice.prototype.compileNode = function(o) { - var compiled, compiledText, from, fromCompiled, to, toStr, _ref2; - _ref2 = this.range, to = _ref2.to, from = _ref2.from; + var compiled, compiledText, from, fromCompiled, to, toStr, _ref4; + _ref4 = this.range, to = _ref4.to, from = _ref4.from; fromCompiled = from && from.compileToFragments(o, LEVEL_PAREN) || [this.makeCode('0')]; if (to) { compiled = to.compileToFragments(o, LEVEL_PAREN); @@ -1322,10 +1288,10 @@ define(function(require, exports, module) { }; Obj.prototype.assigns = function(name) { - var prop, _i, _len, _ref2; - _ref2 = this.properties; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - prop = _ref2[_i]; + var prop, _i, _len, _ref4; + _ref4 = this.properties; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + prop = _ref4[_i]; if (prop.assigns(name)) { return true; } @@ -1358,11 +1324,11 @@ define(function(require, exports, module) { } answer = []; compiledObjs = (function() { - var _i, _len, _ref2, _results; - _ref2 = this.objects; + var _i, _len, _ref4, _results; + _ref4 = this.objects; _results = []; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - obj = _ref2[_i]; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + obj = _ref4[_i]; _results.push(obj.compileToFragments(o, LEVEL_LIST)); } return _results; @@ -1385,10 +1351,10 @@ define(function(require, exports, module) { }; Arr.prototype.assigns = function(name) { - var obj, _i, _len, _ref2; - _ref2 = this.objects; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - obj = _ref2[_i]; + var obj, _i, _len, _ref4; + _ref4 = this.objects; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + obj = _ref4[_i]; if (obj.assigns(name)) { return true; } @@ -1442,10 +1408,10 @@ define(function(require, exports, module) { }; Class.prototype.addBoundFunctions = function(o) { - var bvar, lhs, _i, _len, _ref2; - _ref2 = this.boundFuncs; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - bvar = _ref2[_i]; + var bvar, lhs, _i, _len, _ref4; + _ref4 = this.boundFuncs; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + bvar = _ref4[_i]; lhs = (new Value(new Literal("this"), [new Access(bvar)])).compile(o); this.ctor.body.unshift(new Literal("" + lhs + " = " + (utility('bind')) + "(" + lhs + ", this)")); } @@ -1472,12 +1438,15 @@ define(function(require, exports, module) { if (func instanceof Code) { assign = this.ctor = func; } else { - this.externalCtor = o.classScope.freeVariable('class'); + this.externalCtor = o.scope.freeVariable('class'); assign = new Assign(new Literal(this.externalCtor), func); } } else { if (assign.variable["this"]) { func["static"] = true; + if (func.bound) { + func.context = name; + } } else { assign.variable = new Value(new Literal(name), [new Access(new Literal('prototype')), new Access(base)]); if (func instanceof Code && func.bound) { @@ -1495,29 +1464,26 @@ define(function(require, exports, module) { }; Class.prototype.walkBody = function(name, o) { - return this.traverseChildren(false, (function(_this) { - return function(child) { - var cont, exps, i, node, _i, _len, _ref2; - cont = true; - if (child instanceof Class) { - return false; - } - if (child instanceof Block) { - _ref2 = exps = child.expressions; - for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { - node = _ref2[i]; - if (node instanceof Assign && node.variable.looksStatic(name)) { - node.value["static"] = true; - } else if (node instanceof Value && node.isObject(true)) { - cont = false; - exps[i] = _this.addProperties(node, name, o); - } + var _this = this; + return this.traverseChildren(false, function(child) { + var cont, exps, i, node, _i, _len, _ref4; + cont = true; + if (child instanceof Class) { + return false; + } + if (child instanceof Block) { + _ref4 = exps = child.expressions; + for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { + node = _ref4[i]; + if (node instanceof Value && node.isObject(true)) { + cont = false; + exps[i] = _this.addProperties(node, name, o); } - child.expressions = exps = flatten(exps); } - return cont && !(child instanceof Class); - }; - })(this)); + child.expressions = exps = flatten(exps); + } + return cont && !(child instanceof Class); + }); }; Class.prototype.hoistDirectivePrologue = function() { @@ -1530,53 +1496,62 @@ define(function(require, exports, module) { return this.directives = expressions.splice(0, index); }; - Class.prototype.ensureConstructor = function(name) { - if (!this.ctor) { - this.ctor = new Code; - if (this.externalCtor) { - this.ctor.body.push(new Literal("" + this.externalCtor + ".apply(this, arguments)")); - } else if (this.parent) { - this.ctor.body.push(new Literal("" + name + ".__super__.constructor.apply(this, arguments)")); - } - this.ctor.body.makeReturn(); - this.body.expressions.unshift(this.ctor); - } + Class.prototype.ensureConstructor = function(name, o) { + var missing, ref, superCall; + missing = !this.ctor; + this.ctor || (this.ctor = new Code); this.ctor.ctor = this.ctor.name = name; this.ctor.klass = null; - return this.ctor.noReturn = true; + this.ctor.noReturn = true; + if (missing) { + if (this.parent) { + superCall = new Literal("" + name + ".__super__.constructor.apply(this, arguments)"); + } + if (this.externalCtor) { + superCall = new Literal("" + this.externalCtor + ".apply(this, arguments)"); + } + if (superCall) { + ref = new Literal(o.scope.freeVariable('ref')); + this.ctor.body.unshift(new Assign(ref, superCall)); + } + this.addBoundFunctions(o); + if (superCall) { + this.ctor.body.push(ref); + this.ctor.body.makeReturn(); + } + return this.body.expressions.unshift(this.ctor); + } else { + return this.addBoundFunctions(o); + } }; Class.prototype.compileNode = function(o) { - var args, argumentsNode, func, jumpNode, klass, lname, name, superClass, _ref2; - if (jumpNode = this.body.jumps()) { - jumpNode.error('Class bodies cannot contain pure statements'); - } - if (argumentsNode = this.body.contains(isLiteralArguments)) { - argumentsNode.error("Class bodies shouldn't reference arguments"); - } - name = this.determineName() || '_Class'; + var call, decl, klass, lname, name, params, _ref4; + decl = this.determineName(); + name = decl || '_Class'; if (name.reserved) { name = "_" + name; } lname = new Literal(name); - func = new Code([], Block.wrap([this.body])); - args = []; - o.classScope = func.makeScope(o.scope); this.hoistDirectivePrologue(); this.setContext(name); this.walkBody(name, o); - this.ensureConstructor(name); - this.addBoundFunctions(o); + this.ensureConstructor(name, o); this.body.spaced = true; - this.body.expressions.push(lname); - if (this.parent) { - superClass = new Literal(o.classScope.freeVariable('super', false)); - this.body.expressions.unshift(new Extends(lname, superClass)); - func.params.push(new Param(superClass)); - args.push(this.parent); + if (!(this.ctor instanceof Code)) { + this.body.expressions.unshift(this.ctor); } - (_ref2 = this.body.expressions).unshift.apply(_ref2, this.directives); - klass = new Parens(new Call(func, args)); + this.body.expressions.push(lname); + (_ref4 = this.body.expressions).unshift.apply(_ref4, this.directives); + call = Closure.wrap(this.body); + if (this.parent) { + this.superClass = new Literal(o.scope.freeVariable('super', false)); + this.body.expressions.unshift(new Extends(lname, this.superClass)); + call.args.push(this.parent); + params = call.variable.params || call.variable.base.params; + params.push(new Param(this.superClass)); + } + klass = new Parens(call, true); if (this.variable) { klass = new Assign(this.variable, klass); } @@ -1591,13 +1566,13 @@ define(function(require, exports, module) { __extends(Assign, _super); function Assign(variable, value, context, options) { - var forbidden, name, _ref2; + var forbidden, name, _ref4; this.variable = variable; this.value = value; this.context = context; this.param = options && options.param; this.subpattern = options && options.subpattern; - forbidden = (_ref2 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0); + forbidden = (_ref4 = (name = this.variable.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref4) >= 0); if (forbidden && this.context !== 'object') { this.variable.error("variable name may not be \"" + name + "\""); } @@ -1618,7 +1593,7 @@ define(function(require, exports, module) { }; Assign.prototype.compileNode = function(o) { - var answer, compiledName, isValue, match, name, val, varBase, _ref2, _ref3, _ref4; + var answer, compiledName, isValue, match, name, val, varBase, _ref4, _ref5, _ref6, _ref7; if (isValue = this.variable instanceof Value) { if (this.variable.isArray() || this.variable.isObject()) { return this.compilePatternMatch(o); @@ -1626,7 +1601,7 @@ define(function(require, exports, module) { if (this.variable.isSplice()) { return this.compileSplice(o); } - if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') { + if ((_ref4 = this.context) === '||=' || _ref4 === '&&=' || _ref4 === '?=') { return this.compileConditional(o); } } @@ -1646,10 +1621,10 @@ define(function(require, exports, module) { } } if (this.value instanceof Code && (match = METHOD_DEF.exec(name))) { - if (match[2]) { + if (match[1]) { this.value.klass = match[1]; } - this.value.name = (_ref3 = (_ref4 = match[3]) != null ? _ref4 : match[4]) != null ? _ref3 : match[5]; + this.value.name = (_ref5 = (_ref6 = (_ref7 = match[2]) != null ? _ref7 : match[3]) != null ? _ref6 : match[4]) != null ? _ref5 : match[5]; } val = this.value.compileToFragments(o, LEVEL_LIST); if (this.context === 'object') { @@ -1664,7 +1639,7 @@ define(function(require, exports, module) { }; Assign.prototype.compilePatternMatch = function(o) { - var acc, assigns, code, fragments, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, vvarText, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; + var acc, assigns, code, fragments, i, idx, isObject, ivar, name, obj, objects, olen, ref, rest, splat, top, val, value, vvar, vvarText, _i, _len, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; top = o.level === LEVEL_TOP; value = this.value; objects = this.variable.base.objects; @@ -1679,14 +1654,14 @@ define(function(require, exports, module) { isObject = this.variable.isObject(); if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) { if (obj instanceof Assign) { - _ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base), obj = _ref2.value; + _ref4 = obj, (_ref5 = _ref4.variable, idx = _ref5.base), obj = _ref4.value; } else { idx = isObject ? obj["this"] ? obj.properties[0].name : obj : new Literal(0); } acc = IDENTIFIER.test(idx.unwrap().value || 0); value = new Value(value); value.properties.push(new (acc ? Access : Index)(idx)); - if (_ref4 = obj.unwrap().value, __indexOf.call(RESERVED, _ref4) >= 0) { + if (_ref6 = obj.unwrap().value, __indexOf.call(RESERVED, _ref6) >= 0) { obj.error("assignment to a reserved word: " + (obj.compile(o))); } return new Assign(obj, value, null, { @@ -1707,10 +1682,10 @@ define(function(require, exports, module) { idx = i; if (isObject) { if (obj instanceof Assign) { - _ref5 = obj, (_ref6 = _ref5.variable, idx = _ref6.base), obj = _ref5.value; + _ref7 = obj, (_ref8 = _ref7.variable, idx = _ref8.base), obj = _ref7.value; } else { if (obj.base instanceof Parens) { - _ref7 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref7[0], idx = _ref7[1]; + _ref9 = new Value(obj.unwrapAll()).cacheReference(o), obj = _ref9[0], idx = _ref9[1]; } else { idx = obj["this"] ? obj.properties[0].name : obj; } @@ -1761,38 +1736,29 @@ define(function(require, exports, module) { }; Assign.prototype.compileConditional = function(o) { - var fragments, left, right, _ref2; - _ref2 = this.variable.cacheReference(o), left = _ref2[0], right = _ref2[1]; + var left, right, _ref4; + _ref4 = this.variable.cacheReference(o), left = _ref4[0], right = _ref4[1]; if (!left.properties.length && left.base instanceof Literal && left.base.value !== "this" && !o.scope.check(left.base.value)) { this.variable.error("the variable \"" + left.base.value + "\" can't be assigned with " + this.context + " because it has not been declared before"); } if (__indexOf.call(this.context, "?") >= 0) { o.isExistentialEquals = true; - return new If(new Existence(left), right, { - type: 'if' - }).addElse(new Assign(right, this.value, '=')).compileToFragments(o); - } else { - fragments = new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compileToFragments(o); - if (o.level <= LEVEL_LIST) { - return fragments; - } else { - return this.wrapInBraces(fragments); - } } + return new Op(this.context.slice(0, -1), left, new Assign(right, this.value, '=')).compileToFragments(o); }; Assign.prototype.compileSplice = function(o) { - var answer, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref2, _ref3, _ref4; - _ref2 = this.variable.properties.pop().range, from = _ref2.from, to = _ref2.to, exclusive = _ref2.exclusive; + var answer, exclusive, from, fromDecl, fromRef, name, to, valDef, valRef, _ref4, _ref5, _ref6; + _ref4 = this.variable.properties.pop().range, from = _ref4.from, to = _ref4.to, exclusive = _ref4.exclusive; name = this.variable.compile(o); if (from) { - _ref3 = this.cacheToCodeFragments(from.cache(o, LEVEL_OP)), fromDecl = _ref3[0], fromRef = _ref3[1]; + _ref5 = this.cacheToCodeFragments(from.cache(o, LEVEL_OP)), fromDecl = _ref5[0], fromRef = _ref5[1]; } else { fromDecl = fromRef = '0'; } if (to) { - if (from instanceof Value && from.isSimpleNumber() && to instanceof Value && to.isSimpleNumber()) { - to = to.compile(o) - fromRef; + if ((from != null ? from.isSimpleNumber() : void 0) && to.isSimpleNumber()) { + to = +to.compile(o) - +fromRef; if (!exclusive) { to += 1; } @@ -1805,7 +1771,7 @@ define(function(require, exports, module) { } else { to = "9e9"; } - _ref4 = this.value.cache(o, LEVEL_LIST), valDef = _ref4[0], valRef = _ref4[1]; + _ref6 = this.value.cache(o, LEVEL_LIST), valDef = _ref6[0], valRef = _ref6[1]; answer = [].concat(this.makeCode("[].splice.apply(" + name + ", [" + fromDecl + ", " + to + "].concat("), valDef, this.makeCode(")), "), valRef); if (o.level > LEVEL_TOP) { return this.wrapInBraces(answer); @@ -1825,6 +1791,9 @@ define(function(require, exports, module) { this.params = params || []; this.body = body || new Block; this.bound = tag === 'boundfunc'; + if (this.bound) { + this.context = '_this'; + } } Code.prototype.children = ['params', 'body']; @@ -1835,43 +1804,29 @@ define(function(require, exports, module) { Code.prototype.jumps = NO; - Code.prototype.makeScope = function(parentScope) { - return new Scope(parentScope, this.body, this); - }; - Code.prototype.compileNode = function(o) { - var answer, boundfunc, code, exprs, i, lit, p, param, params, ref, splats, uniqs, val, wasEmpty, wrapper, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _len5, _m, _n, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; - if (this.bound && ((_ref2 = o.scope.method) != null ? _ref2.bound : void 0)) { - this.context = o.scope.method.context; - } - if (this.bound && !this.context) { - this.context = '_this'; - wrapper = new Code([new Param(new Literal(this.context))], new Block([this])); - boundfunc = new Call(wrapper, [new Literal('this')]); - boundfunc.updateLocationDataIfMissing(this.locationData); - return boundfunc.compileNode(o); - } - o.scope = del(o, 'classScope') || this.makeScope(o.scope); + var answer, code, exprs, i, idt, lit, p, param, params, ref, splats, uniqs, val, wasEmpty, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref4, _ref5, _ref6, _ref7, _ref8; + o.scope = new Scope(o.scope, this.body, this); o.scope.shared = del(o, 'sharedScope'); o.indent += TAB; delete o.bare; delete o.isExistentialEquals; params = []; exprs = []; - _ref3 = this.params; - for (_i = 0, _len = _ref3.length; _i < _len; _i++) { - param = _ref3[_i]; - o.scope.parameter(param.asReference(o)); - } + this.eachParamName(function(name) { + if (!o.scope.check(name)) { + return o.scope.parameter(name); + } + }); _ref4 = this.params; - for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) { - param = _ref4[_j]; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + param = _ref4[_i]; if (!param.splat) { continue; } _ref5 = this.params; - for (_k = 0, _len2 = _ref5.length; _k < _len2; _k++) { - p = _ref5[_k].name; + for (_j = 0, _len1 = _ref5.length; _j < _len1; _j++) { + p = _ref5[_j].name; if (p["this"]) { p = p.properties[0].name; } @@ -1880,11 +1835,11 @@ define(function(require, exports, module) { } } splats = new Assign(new Value(new Arr((function() { - var _l, _len3, _ref6, _results; + var _k, _len2, _ref6, _results; _ref6 = this.params; _results = []; - for (_l = 0, _len3 = _ref6.length; _l < _len3; _l++) { - p = _ref6[_l]; + for (_k = 0, _len2 = _ref6.length; _k < _len2; _k++) { + p = _ref6[_k]; _results.push(p.asReference(o)); } return _results; @@ -1892,8 +1847,8 @@ define(function(require, exports, module) { break; } _ref6 = this.params; - for (_l = 0, _len3 = _ref6.length; _l < _len3; _l++) { - param = _ref6[_l]; + for (_k = 0, _len2 = _ref6.length; _k < _len2; _k++) { + param = _ref6[_k]; if (param.isComplex()) { val = ref = param.asReference(o); if (param.value) { @@ -1921,7 +1876,7 @@ define(function(require, exports, module) { if (exprs.length) { (_ref7 = this.body.expressions).unshift.apply(_ref7, exprs); } - for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) { + for (i = _l = 0, _len3 = params.length; _l < _len3; i = ++_l) { p = params[i]; params[i] = p.compileToFragments(o); o.scope.parameter(fragmentsToText(params[i])); @@ -1936,13 +1891,21 @@ define(function(require, exports, module) { if (!(wasEmpty || this.noReturn)) { this.body.makeReturn(); } + if (this.bound) { + if ((_ref8 = o.scope.parent.method) != null ? _ref8.bound : void 0) { + this.bound = this.context = o.scope.parent.method.context; + } else if (!this["static"]) { + o.scope.parent.assign('_this', 'this'); + } + } + idt = o.indent; code = 'function'; if (this.ctor) { code += ' ' + this.name; } code += '('; answer = [this.makeCode(code)]; - for (i = _n = 0, _len5 = params.length; _n < _len5; i = ++_n) { + for (i = _m = 0, _len4 = params.length; _m < _len4; i = ++_m) { p = params[i]; if (i) { answer.push(this.makeCode(", ")); @@ -1965,11 +1928,11 @@ define(function(require, exports, module) { }; Code.prototype.eachParamName = function(iterator) { - var param, _i, _len, _ref2, _results; - _ref2 = this.params; + var param, _i, _len, _ref4, _results; + _ref4 = this.params; _results = []; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - param = _ref2[_i]; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + param = _ref4[_i]; _results.push(param.eachName(iterator)); } return _results; @@ -1989,11 +1952,11 @@ define(function(require, exports, module) { __extends(Param, _super); function Param(name, value, splat) { - var _ref2; + var _ref4; this.name = name; this.value = value; this.splat = splat; - if (_ref2 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref2) >= 0) { + if (_ref4 = (name = this.name.unwrapAll().value), __indexOf.call(STRICT_PROSCRIBED, _ref4) >= 0) { this.name.error("parameter name \"" + name + "\" is not allowed"); } } @@ -2022,7 +1985,6 @@ define(function(require, exports, module) { if (this.splat) { node = new Splat(node); } - node.updateLocationDataIfMissing(this.locationData); return this.reference = node; }; @@ -2031,7 +1993,7 @@ define(function(require, exports, module) { }; Param.prototype.eachName = function(iterator, name) { - var atParam, node, obj, _i, _len, _ref2; + var atParam, node, obj, _i, _len, _ref4; if (name == null) { name = this.name; } @@ -2048,9 +2010,9 @@ define(function(require, exports, module) { if (name instanceof Value) { return atParam(name); } - _ref2 = name.objects; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - obj = _ref2[_i]; + _ref4 = name.objects; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + obj = _ref4[_i]; if (obj instanceof Assign) { this.eachName(iterator, obj.value.unwrap()); } else if (obj instanceof Splat) { @@ -2126,11 +2088,11 @@ define(function(require, exports, module) { return args[0].concat(node.makeCode(".concat("), concatPart, node.makeCode(")")); } base = (function() { - var _j, _len1, _ref2, _results; - _ref2 = list.slice(0, index); + var _j, _len1, _ref4, _results; + _ref4 = list.slice(0, index); _results = []; - for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { - node = _ref2[_j]; + for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) { + node = _ref4[_j]; _results.push(node.compileToFragments(o, LEVEL_LIST)); } return _results; @@ -2173,17 +2135,17 @@ define(function(require, exports, module) { }; While.prototype.jumps = function() { - var expressions, jumpNode, node, _i, _len; + var expressions, node, _i, _len; expressions = this.body.expressions; if (!expressions.length) { return false; } for (_i = 0, _len = expressions.length; _i < _len; _i++) { node = expressions[_i]; - if (jumpNode = node.jumps({ + if (node.jumps({ loop: true })) { - return jumpNode; + return node; } } return false; @@ -2270,17 +2232,17 @@ define(function(require, exports, module) { }; Op.prototype.isComplex = function() { - var _ref2; - return !(this.isUnary() && ((_ref2 = this.operator) === '+' || _ref2 === '-')) || this.first.isComplex(); + var _ref4; + return !(this.isUnary() && ((_ref4 = this.operator) === '+' || _ref4 === '-')) || this.first.isComplex(); }; Op.prototype.isChainable = function() { - var _ref2; - return (_ref2 = this.operator) === '<' || _ref2 === '>' || _ref2 === '>=' || _ref2 === '<=' || _ref2 === '===' || _ref2 === '!=='; + var _ref4; + return (_ref4 = this.operator) === '<' || _ref4 === '>' || _ref4 === '>=' || _ref4 === '<=' || _ref4 === '===' || _ref4 === '!=='; }; Op.prototype.invert = function() { - var allInvertable, curr, fst, op, _ref2; + var allInvertable, curr, fst, op, _ref4; if (this.isChainable() && this.first.isChainable()) { allInvertable = true; curr = this; @@ -2306,7 +2268,7 @@ define(function(require, exports, module) { return this; } else if (this.second) { return new Parens(this).invert(); - } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref2 = fst.operator) === '!' || _ref2 === 'in' || _ref2 === 'instanceof')) { + } else if (this.operator === '!' && (fst = this.first.unwrap()) instanceof Op && ((_ref4 = fst.operator) === '!' || _ref4 === 'in' || _ref4 === 'instanceof')) { return fst; } else { return new Op('!', this); @@ -2314,17 +2276,17 @@ define(function(require, exports, module) { }; Op.prototype.unfoldSoak = function(o) { - var _ref2; - return ((_ref2 = this.operator) === '++' || _ref2 === '--' || _ref2 === 'delete') && unfoldSoak(o, this, 'first'); + var _ref4; + return ((_ref4 = this.operator) === '++' || _ref4 === '--' || _ref4 === 'delete') && unfoldSoak(o, this, 'first'); }; Op.prototype.generateDo = function(exp) { - var call, func, param, passedParams, ref, _i, _len, _ref2; + var call, func, param, passedParams, ref, _i, _len, _ref4; passedParams = []; func = exp instanceof Assign && (ref = exp.value.unwrap()) instanceof Code ? ref : exp; - _ref2 = func.params || []; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - param = _ref2[_i]; + _ref4 = func.params || []; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + param = _ref4[_i]; if (param.value) { passedParams.push(param.value); delete param.value; @@ -2338,7 +2300,7 @@ define(function(require, exports, module) { }; Op.prototype.compileNode = function(o) { - var answer, isChain, _ref2, _ref3; + var answer, isChain, _ref4, _ref5; isChain = this.isChainable() && this.first.isChainable(); if (!isChain) { this.first.front = this.front; @@ -2346,7 +2308,7 @@ define(function(require, exports, module) { if (this.operator === 'delete' && o.scope.check(this.first.unwrapAll().value)) { this.error('delete operand may not be argument or var'); } - if (((_ref2 = this.operator) === '--' || _ref2 === '++') && (_ref3 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref3) >= 0)) { + if (((_ref4 = this.operator) === '--' || _ref4 === '++') && (_ref5 = this.first.unwrapAll().value, __indexOf.call(STRICT_PROSCRIBED, _ref5) >= 0)) { this.error("cannot increment/decrement \"" + (this.first.unwrapAll().value) + "\""); } if (this.isUnary()) { @@ -2367,8 +2329,8 @@ define(function(require, exports, module) { }; Op.prototype.compileChain = function(o) { - var fragments, fst, shared, _ref2; - _ref2 = this.first.second.cache(o), this.first.second = _ref2[0], shared = _ref2[1]; + var fragments, fst, shared, _ref4; + _ref4 = this.first.second.cache(o), this.first.second = _ref4[0], shared = _ref4[1]; fst = this.first.compileToFragments(o, LEVEL_OP); fragments = fst.concat(this.makeCode(" " + (this.invert ? '&&' : '||') + " "), shared.compileToFragments(o), this.makeCode(" " + this.operator + " "), this.second.compileToFragments(o, LEVEL_OP)); return this.wrapInBraces(fragments); @@ -2376,7 +2338,7 @@ define(function(require, exports, module) { Op.prototype.compileExistence = function(o) { var fst, ref; - if (this.first.isComplex()) { + if (!o.isExistentialEquals && this.first.isComplex()) { ref = new Literal(o.scope.freeVariable('ref')); fst = new Parens(new Assign(ref, this.first)); } else { @@ -2435,11 +2397,11 @@ define(function(require, exports, module) { In.prototype.invert = NEGATE; In.prototype.compileNode = function(o) { - var hasSplat, obj, _i, _len, _ref2; + var hasSplat, obj, _i, _len, _ref4; if (this.array instanceof Value && this.array.isArray()) { - _ref2 = this.array.base.objects; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - obj = _ref2[_i]; + _ref4 = this.array.base.objects; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + obj = _ref4[_i]; if (!(obj instanceof Splat)) { continue; } @@ -2454,16 +2416,16 @@ define(function(require, exports, module) { }; In.prototype.compileOrTest = function(o) { - var cmp, cnj, i, item, ref, sub, tests, _i, _len, _ref2, _ref3, _ref4; + var cmp, cnj, i, item, ref, sub, tests, _i, _len, _ref4, _ref5, _ref6; if (this.array.base.objects.length === 0) { return [this.makeCode("" + (!!this.negated))]; } - _ref2 = this.object.cache(o, LEVEL_OP), sub = _ref2[0], ref = _ref2[1]; - _ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1]; + _ref4 = this.object.cache(o, LEVEL_OP), sub = _ref4[0], ref = _ref4[1]; + _ref5 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref5[0], cnj = _ref5[1]; tests = []; - _ref4 = this.array.base.objects; - for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { - item = _ref4[i]; + _ref6 = this.array.base.objects; + for (i = _i = 0, _len = _ref6.length; _i < _len; i = ++_i) { + item = _ref6[i]; if (i) { tests.push(this.makeCode(cnj)); } @@ -2477,8 +2439,8 @@ define(function(require, exports, module) { }; In.prototype.compileLoopTest = function(o) { - var fragments, ref, sub, _ref2; - _ref2 = this.object.cache(o, LEVEL_LIST), sub = _ref2[0], ref = _ref2[1]; + var fragments, ref, sub, _ref4; + _ref4 = this.object.cache(o, LEVEL_LIST), sub = _ref4[0], ref = _ref4[1]; fragments = [].concat(this.makeCode(utility('indexOf') + ".call("), this.array.compileToFragments(o, LEVEL_LIST), this.makeCode(", "), ref, this.makeCode(") " + (this.negated ? '< 0' : '>= 0'))); if (fragmentsToText(sub) === fragmentsToText(ref)) { return fragments; @@ -2514,8 +2476,8 @@ define(function(require, exports, module) { Try.prototype.isStatement = YES; Try.prototype.jumps = function(o) { - var _ref2; - return this.attempt.jumps(o) || ((_ref2 = this.recovery) != null ? _ref2.jumps(o) : void 0); + var _ref4; + return this.attempt.jumps(o) || ((_ref4 = this.recovery) != null ? _ref4.jumps(o) : void 0); }; Try.prototype.makeReturn = function(res) { @@ -2576,11 +2538,11 @@ define(function(require, exports, module) { Existence.prototype.invert = NEGATE; Existence.prototype.compileNode = function(o) { - var cmp, cnj, code, _ref2; + var cmp, cnj, code, _ref4; this.expression.front = this.front; code = this.expression.compile(o, LEVEL_OP); if (IDENTIFIER.test(code) && !o.scope.check(code)) { - _ref2 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref2[0], cnj = _ref2[1]; + _ref4 = this.negated ? ['===', '||'] : ['!==', '&&'], cmp = _ref4[0], cnj = _ref4[1]; code = "typeof " + code + " " + cmp + " \"undefined\" " + cnj + " " + code + " " + cmp + " null"; } else { code = "" + code + " " + (this.negated ? '==' : '!=') + " null"; @@ -2633,13 +2595,13 @@ define(function(require, exports, module) { __extends(For, _super); function For(body, source) { - var _ref2; + var _ref4; this.source = source.source, this.guard = source.guard, this.step = source.step, this.name = source.name, this.index = source.index; this.body = Block.wrap([body]); this.own = !!source.own; this.object = !!source.object; if (this.object) { - _ref2 = [this.index, this.name], this.name = _ref2[0], this.index = _ref2[1]; + _ref4 = [this.index, this.name], this.name = _ref4[0], this.index = _ref4[1]; } if (this.index instanceof Value) { this.index.error('index cannot be a pattern matching expression'); @@ -2653,7 +2615,7 @@ define(function(require, exports, module) { this.name.error('cannot pattern match over range loops'); } if (this.own && !this.object) { - this.name.error('cannot use own with for-in'); + this.index.error('cannot use own with for-in'); } this.returns = false; } @@ -2661,9 +2623,9 @@ define(function(require, exports, module) { For.prototype.children = ['body', 'source', 'guard', 'step']; For.prototype.compileNode = function(o) { - var body, bodyFragments, compare, compareDown, declare, declareDown, defPart, defPartFragments, down, forPartFragments, guardPart, idt1, increment, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, step, stepNum, stepVar, svar, varPart, _ref2, _ref3; + var body, bodyFragments, compare, compareDown, declare, declareDown, defPart, defPartFragments, down, forPartFragments, guardPart, idt1, increment, index, ivar, kvar, kvarAssign, lastJumps, lvar, name, namePart, ref, resultPart, returnResult, rvar, scope, source, step, stepNum, stepVar, svar, varPart, _ref4, _ref5; body = Block.wrap([this.body]); - lastJumps = (_ref2 = last(body.expressions)) != null ? _ref2.jumps() : void 0; + lastJumps = (_ref4 = last(body.expressions)) != null ? _ref4.jumps() : void 0; if (lastJumps && lastJumps instanceof Return) { this.returns = false; } @@ -2684,8 +2646,8 @@ define(function(require, exports, module) { kvar = (this.range && name) || index || ivar; kvarAssign = kvar !== ivar ? "" + kvar + " = " : ""; if (this.step && !this.range) { - _ref3 = this.cacheToCodeFragments(this.step.cache(o, LEVEL_LIST)), step = _ref3[0], stepVar = _ref3[1]; - stepNum = stepVar.match(NUMBER); + _ref5 = this.cacheToCodeFragments(this.step.cache(o, LEVEL_LIST)), step = _ref5[0], stepVar = _ref5[1]; + stepNum = stepVar.match(SIMPLENUM); } if (this.pattern) { name = ivar; @@ -2713,7 +2675,7 @@ define(function(require, exports, module) { if (step !== stepVar) { defPart += "" + this.tab + step + ";\n"; } - if (!(this.step && stepNum && (down = parseNum(stepNum[0]) < 0))) { + if (!(this.step && stepNum && (down = +stepNum < 0))) { lvar = scope.freeVariable('len'); } declare = "" + kvarAssign + ivar + " = 0, " + lvar + " = " + svar + ".length"; @@ -2774,24 +2736,24 @@ define(function(require, exports, module) { }; For.prototype.pluckDirectCall = function(o, body) { - var base, defs, expr, fn, idx, ref, val, _i, _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; + var base, defs, expr, fn, idx, ref, val, _i, _len, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; defs = []; - _ref2 = body.expressions; - for (idx = _i = 0, _len = _ref2.length; _i < _len; idx = ++_i) { - expr = _ref2[idx]; + _ref4 = body.expressions; + for (idx = _i = 0, _len = _ref4.length; _i < _len; idx = ++_i) { + expr = _ref4[idx]; expr = expr.unwrapAll(); if (!(expr instanceof Call)) { continue; } - val = (_ref3 = expr.variable) != null ? _ref3.unwrapAll() : void 0; - if (!((val instanceof Code) || (val instanceof Value && ((_ref4 = val.base) != null ? _ref4.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref5 = (_ref6 = val.properties[0].name) != null ? _ref6.value : void 0) === 'call' || _ref5 === 'apply')))) { + val = expr.variable.unwrapAll(); + if (!((val instanceof Code) || (val instanceof Value && ((_ref5 = val.base) != null ? _ref5.unwrapAll() : void 0) instanceof Code && val.properties.length === 1 && ((_ref6 = (_ref7 = val.properties[0].name) != null ? _ref7.value : void 0) === 'call' || _ref6 === 'apply')))) { continue; } - fn = ((_ref7 = val.base) != null ? _ref7.unwrapAll() : void 0) || val; + fn = ((_ref8 = val.base) != null ? _ref8.unwrapAll() : void 0) || val; ref = new Literal(o.scope.freeVariable('fn')); base = new Value(ref); if (val.base) { - _ref8 = [base, val], val.base = _ref8[0], base = _ref8[1]; + _ref9 = [base, val], val.base = _ref9[0], base = _ref9[1]; } body.expressions[idx] = new Call(base, expr.args); defs = defs.concat(this.makeCode(this.tab), new Assign(ref, fn).compileToFragments(o, LEVEL_TOP), this.makeCode(';\n')); @@ -2817,49 +2779,49 @@ define(function(require, exports, module) { Switch.prototype.isStatement = YES; Switch.prototype.jumps = function(o) { - var block, conds, jumpNode, _i, _len, _ref2, _ref3, _ref4; + var block, conds, _i, _len, _ref4, _ref5, _ref6; if (o == null) { o = { block: true }; } - _ref2 = this.cases; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - _ref3 = _ref2[_i], conds = _ref3[0], block = _ref3[1]; - if (jumpNode = block.jumps(o)) { - return jumpNode; + _ref4 = this.cases; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + _ref5 = _ref4[_i], conds = _ref5[0], block = _ref5[1]; + if (block.jumps(o)) { + return block; } } - return (_ref4 = this.otherwise) != null ? _ref4.jumps(o) : void 0; + return (_ref6 = this.otherwise) != null ? _ref6.jumps(o) : void 0; }; Switch.prototype.makeReturn = function(res) { - var pair, _i, _len, _ref2, _ref3; - _ref2 = this.cases; - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - pair = _ref2[_i]; + var pair, _i, _len, _ref4, _ref5; + _ref4 = this.cases; + for (_i = 0, _len = _ref4.length; _i < _len; _i++) { + pair = _ref4[_i]; pair[1].makeReturn(res); } if (res) { this.otherwise || (this.otherwise = new Block([new Literal('void 0')])); } - if ((_ref3 = this.otherwise) != null) { - _ref3.makeReturn(res); + if ((_ref5 = this.otherwise) != null) { + _ref5.makeReturn(res); } return this; }; Switch.prototype.compileNode = function(o) { - var block, body, cond, conditions, expr, fragments, i, idt1, idt2, _i, _j, _len, _len1, _ref2, _ref3, _ref4; + var block, body, cond, conditions, expr, fragments, i, idt1, idt2, _i, _j, _len, _len1, _ref4, _ref5, _ref6; idt1 = o.indent + TAB; idt2 = o.indent = idt1 + TAB; fragments = [].concat(this.makeCode(this.tab + "switch ("), (this.subject ? this.subject.compileToFragments(o, LEVEL_PAREN) : this.makeCode("false")), this.makeCode(") {\n")); - _ref2 = this.cases; - for (i = _i = 0, _len = _ref2.length; _i < _len; i = ++_i) { - _ref3 = _ref2[i], conditions = _ref3[0], block = _ref3[1]; - _ref4 = flatten([conditions]); - for (_j = 0, _len1 = _ref4.length; _j < _len1; _j++) { - cond = _ref4[_j]; + _ref4 = this.cases; + for (i = _i = 0, _len = _ref4.length; _i < _len; i = ++_i) { + _ref5 = _ref4[i], conditions = _ref5[0], block = _ref5[1]; + _ref6 = flatten([conditions]); + for (_j = 0, _len1 = _ref6.length; _j < _len1; _j++) { + cond = _ref6[_j]; if (!this.subject) { cond = cond.invert(); } @@ -2905,13 +2867,13 @@ define(function(require, exports, module) { If.prototype.children = ['condition', 'body', 'elseBody']; If.prototype.bodyNode = function() { - var _ref2; - return (_ref2 = this.body) != null ? _ref2.unwrap() : void 0; + var _ref4; + return (_ref4 = this.body) != null ? _ref4.unwrap() : void 0; }; If.prototype.elseBodyNode = function() { - var _ref2; - return (_ref2 = this.elseBody) != null ? _ref2.unwrap() : void 0; + var _ref4; + return (_ref4 = this.elseBody) != null ? _ref4.unwrap() : void 0; }; If.prototype.addElse = function(elseBody) { @@ -2926,13 +2888,13 @@ define(function(require, exports, module) { }; If.prototype.isStatement = function(o) { - var _ref2; - return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref2 = this.elseBodyNode()) != null ? _ref2.isStatement(o) : void 0); + var _ref4; + return (o != null ? o.level : void 0) === LEVEL_TOP || this.bodyNode().isStatement(o) || ((_ref4 = this.elseBodyNode()) != null ? _ref4.isStatement(o) : void 0); }; If.prototype.jumps = function(o) { - var _ref2; - return this.body.jumps(o) || ((_ref2 = this.elseBody) != null ? _ref2.jumps(o) : void 0); + var _ref4; + return this.body.jumps(o) || ((_ref4 = this.elseBody) != null ? _ref4.jumps(o) : void 0); }; If.prototype.compileNode = function(o) { @@ -3014,6 +2976,52 @@ define(function(require, exports, module) { })(Base); + Closure = { + wrap: function(expressions, statement, noReturn) { + var args, argumentsNode, call, func, meth; + if (expressions.jumps()) { + return expressions; + } + func = new Code([], Block.wrap([expressions])); + args = []; + argumentsNode = expressions.contains(this.isLiteralArguments); + if (argumentsNode && expressions.classBody) { + argumentsNode.error("Class bodies shouldn't reference arguments"); + } + if (argumentsNode || expressions.contains(this.isLiteralThis)) { + meth = new Literal(argumentsNode ? 'apply' : 'call'); + args = [new Literal('this')]; + if (argumentsNode) { + args.push(new Literal('arguments')); + } + func = new Value(func, [new Access(meth)]); + } + func.noReturn = noReturn; + call = new Call(func, args); + if (statement) { + return Block.wrap([call]); + } else { + return call; + } + }, + isLiteralArguments: function(node) { + return node instanceof Literal && node.value === 'arguments' && !node.asKey; + }, + isLiteralThis: function(node) { + return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper); + } + }; + + unfoldSoak = function(o, parent, name) { + var ifn; + if (!(ifn = parent[name].unfoldSoak(o))) { + return; + } + parent[name] = ifn.body; + ifn.body = new Value(parent); + return ifn; + }; + UTILITIES = { "extends": function() { return "function(child, parent) { for (var key in parent) { if (" + (utility('hasProp')) + ".call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }"; @@ -3052,16 +3060,10 @@ define(function(require, exports, module) { SIMPLENUM = /^[+-]?\d+$/; - HEXNUM = /^[+-]?0x[\da-f]+/i; - - NUMBER = /^[+-]?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)$/i; - - METHOD_DEF = RegExp("^(" + IDENTIFIER_STR + ")(\\.prototype)?(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\])$"); + METHOD_DEF = RegExp("^(?:(" + IDENTIFIER_STR + ")\\.prototype(?:\\.(" + IDENTIFIER_STR + ")|\\[(\"(?:[^\\\\\"\\r\\n]|\\\\.)*\"|'(?:[^\\\\'\\r\\n]|\\\\.)*')\\]|\\[(0x[\\da-fA-F]+|\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\]))|(" + IDENTIFIER_STR + ")$"); IS_STRING = /^['"]/; - IS_REGEX = /^\//; - utility = function(name) { var ref; ref = "__" + name; @@ -3074,33 +3076,5 @@ define(function(require, exports, module) { return code.replace(/\s+$/, ''); }; - parseNum = function(x) { - if (x == null) { - return 0; - } else if (x.match(HEXNUM)) { - return parseInt(x, 16); - } else { - return parseFloat(x); - } - }; - - isLiteralArguments = function(node) { - return node instanceof Literal && node.value === 'arguments' && !node.asKey; - }; - - isLiteralThis = function(node) { - return (node instanceof Literal && node.value === 'this' && !node.asKey) || (node instanceof Code && node.bound) || (node instanceof Call && node.isSuper); - }; - - unfoldSoak = function(o, parent, name) { - var ifn; - if (!(ifn = parent[name].unfoldSoak(o))) { - return; - } - parent[name] = ifn.body; - ifn.body = new Value(parent); - return ifn; - }; - }); \ No newline at end of file diff --git a/lib/ace/mode/coffee/rewriter.js b/lib/ace/mode/coffee/rewriter.js index acb5c420..009d17d0 100644 --- a/lib/ace/mode/coffee/rewriter.js +++ b/lib/ace/mode/coffee/rewriter.js @@ -27,7 +27,7 @@ define(function(require, exports, module) { // Generated by CoffeeScript 1.6.3 - var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, left, rite, _i, _len, _ref, + var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, left, rite, _i, _len, _ref, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, __slice = [].slice; @@ -44,9 +44,10 @@ define(function(require, exports, module) { Rewriter.prototype.rewrite = function(tokens) { this.tokens = tokens; this.removeLeadingNewlines(); + this.removeMidExpressionNewlines(); this.closeOpenCalls(); this.closeOpenIndexes(); - this.normalizeLines(); + this.addImplicitIndentation(); this.tagPostfixConditionals(); this.addImplicitBracesAndParens(); this.addLocationDataToGeneratedTokens(); @@ -98,6 +99,17 @@ define(function(require, exports, module) { } }; + Rewriter.prototype.removeMidExpressionNewlines = function() { + return this.scanTokens(function(token, i, tokens) { + var _ref; + if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) { + return 1; + } + tokens.splice(i, 1); + return 0; + }); + }; + Rewriter.prototype.closeOpenCalls = function() { var action, condition; condition = function(token, i) { @@ -176,9 +188,9 @@ define(function(require, exports, module) { var stack; stack = []; return this.scanTokens(function(token, i, tokens) { - var endAllImplicitCalls, endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, nextTag, offset, prevTag, prevToken, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; + var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, nextTag, offset, prevTag, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag, _ref, _ref1, _ref2, _ref3, _ref4, _ref5; tag = token[0]; - prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0]; + prevTag = (i > 0 ? tokens[i - 1] : [])[0]; nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0]; stackTop = function() { return stack[stack.length - 1]; @@ -221,11 +233,6 @@ define(function(require, exports, module) { tokens.splice(i, 0, generate('CALL_END', ')')); return i += 1; }; - endAllImplicitCalls = function() { - while (inImplicitCall()) { - endImplicitCall(); - } - }; startImplicitObject = function(j, startsLine) { var idx; if (startsLine == null) { @@ -317,15 +324,9 @@ define(function(require, exports, module) { startImplicitObject(s, !!startsLine); return forward(2); } - if (inImplicitCall() && __indexOf.call(CALL_CLOSERS, tag) >= 0) { - if (prevTag === 'OUTDENT') { - endImplicitCall(); - return forward(1); - } - if (prevToken.newLine) { - endAllImplicitCalls(); - return forward(1); - } + if (prevTag === 'OUTDENT' && inImplicitCall() && (tag === '.' || tag === '?.' || tag === '::' || tag === '?::')) { + endImplicitCall(); + return forward(1); } if (inImplicitObject() && __indexOf.call(LINEBREAKS, tag) >= 0) { stackTop()[2].sameLine = false; @@ -380,32 +381,30 @@ define(function(require, exports, module) { }); }; - Rewriter.prototype.normalizeLines = function() { + Rewriter.prototype.addImplicitIndentation = function() { var action, condition, indent, outdent, starter; starter = indent = outdent = null; condition = function(token, i) { - var _ref, _ref1, _ref2, _ref3; - return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'TERMINATOR' && (_ref1 = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((_ref2 = token[0]) === 'CATCH' || _ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (_ref3 = token[0], __indexOf.call(CALL_CLOSERS, _ref3) >= 0) && this.tokens[i - 1].newLine; + var _ref, _ref1; + return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((_ref1 = token[0]) === 'CATCH' || _ref1 === 'FINALLY') && (starter === '->' || starter === '=>')); }; action = function(token, i) { return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent); }; return this.scanTokens(function(token, i, tokens) { - var j, tag, _i, _ref, _ref1, _ref2; + var j, tag, _i, _ref, _ref1; tag = token[0]; - if (tag === 'TERMINATOR') { - if (this.tag(i + 1) === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') { - tokens.splice.apply(tokens, [i, 1].concat(__slice.call(this.indentation()))); - return 1; - } - if (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0) { - tokens.splice(i, 1); - return 0; - } + if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') { + tokens.splice(i, 1); + return 0; + } + if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') { + tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation()))); + return 2; } if (tag === 'CATCH') { for (j = _i = 1; _i <= 2; j = ++_i) { - if (!((_ref1 = this.tag(i + j)) === 'OUTDENT' || _ref1 === 'TERMINATOR' || _ref1 === 'FINALLY')) { + if (!((_ref = this.tag(i + j)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) { continue; } tokens.splice.apply(tokens, [i + j, 0].concat(__slice.call(this.indentation()))); @@ -414,7 +413,7 @@ define(function(require, exports, module) { } if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) { starter = tag; - _ref2 = this.indentation(true), indent = _ref2[0], outdent = _ref2[1]; + _ref1 = this.indentation(true), indent = _ref1[0], outdent = _ref1[1]; if (starter === 'THEN') { indent.fromThen = true; } @@ -494,7 +493,7 @@ define(function(require, exports, module) { EXPRESSION_END.push(INVERSES[left] = rite); } - EXPRESSION_CLOSE = ['CATCH', 'THEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); + EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END); IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS']; @@ -510,7 +509,5 @@ define(function(require, exports, module) { LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']; - CALL_CLOSERS = ['.', '?.', '::', '?::']; - }); \ No newline at end of file diff --git a/lib/ace/mode/coffee_highlight_rules.js b/lib/ace/mode/coffee_highlight_rules.js index 94c9476f..c050f78a 100644 --- a/lib/ace/mode/coffee_highlight_rules.js +++ b/lib/ace/mode/coffee_highlight_rules.js @@ -41,7 +41,7 @@ define(function(require, exports, module) { var keywords = ( "this|throw|then|try|typeof|super|switch|return|break|by|continue|" + - "catch|class|in|instanceof|is|isnt|if|else|extends|for|own|" + + "catch|class|in|instanceof|is|isnt|if|else|extends|for|forown|" + "finally|function|while|when|new|no|not|delete|debugger|do|loop|of|off|" + "or|on|unless|until|and|yes" ); @@ -142,7 +142,7 @@ define(function(require, exports, module) { } if (val == "}" && stack.length) { stack.shift(); - this.next = stack.shift() || ""; + this.next = stack.shift(); if (this.next.indexOf("string") != -1) return "paren.string"; } diff --git a/lib/ace/mode/coffee_worker.js b/lib/ace/mode/coffee_worker.js index d68f1296..a5f700f8 100644 --- a/lib/ace/mode/coffee_worker.js +++ b/lib/ace/mode/coffee_worker.js @@ -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) { - errors.push({ + this.sender.emit("error", { row: loc.first_line, column: loc.first_column, endRow: loc.last_line, @@ -64,8 +64,9 @@ oop.inherits(Worker, Mirror); type: "error" }); } + return; } - this.sender.emit("annotate", errors); + this.sender.emit("ok"); }; }).call(Worker.prototype); diff --git a/lib/ace/mode/coldfusion.js b/lib/ace/mode/coldfusion.js index 0b4ea449..fc62a89e 100644 --- a/lib/ace/mode/coldfusion.js +++ b/lib/ace/mode/coldfusion.js @@ -32,29 +32,32 @@ define(function(require, exports, module) { "use strict"; var oop = require("../lib/oop"); -var lang = require("../lib/lang"); -var HtmlMode = require("./html").Mode; +var XmlMode = require("./xml").Mode; +var JavaScriptMode = require("./javascript").Mode; +var CssMode = require("./css").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var ColdfusionHighlightRules = require("./coldfusion_highlight_rules").ColdfusionHighlightRules; -var voidElements = "cfabort|cfapplication|cfargument|cfassociate|cfbreak|cfcache|cfcollection|cfcookie|cfdbinfo|cfdirectory|cfdump|cfelse|cfelseif|cferror|cfexchangecalendar|cfexchangeconnection|cfexchangecontact|cfexchangefilter|cfexchangetask|cfexit|cffeed|cffile|cfflush|cfftp|cfheader|cfhtmlhead|cfhttpparam|cfimage|cfimport|cfinclude|cfindex|cfinsert|cfinvokeargument|cflocation|cflog|cfmailparam|cfNTauthenticate|cfobject|cfobjectcache|cfparam|cfpdfformparam|cfprint|cfprocparam|cfprocresult|cfproperty|cfqueryparam|cfregistry|cfreportparam|cfrethrow|cfreturn|cfschedule|cfsearch|cfset|cfsetting|cfthrow|cfzipparam)".split("|"); - var Mode = function() { - HtmlMode.call(this); + XmlMode.call(this); - this.HighlightRules = ColdfusionHighlightRules; + var highlighter = new ColdfusionHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + + this.$embeds = highlighter.getEmbeds(); + this.createModeDelegates({ + "js-": JavaScriptMode, + "css-": CssMode + }); }; -oop.inherits(Mode, HtmlMode); +oop.inherits(Mode, XmlMode); (function() { - // mix with html void elements - this.voidElements = oop.mixin(lang.arrayToMap(voidElements), this.voidElements); - this.getNextLineIndent = function(state, line, tab) { return this.$getIndent(line); }; - this.$id = "ace/mode/coldfusion"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/csharp.js b/lib/ace/mode/csharp.js index a3b2964f..66644b45 100644 --- a/lib/ace/mode/csharp.js +++ b/lib/ace/mode/csharp.js @@ -3,15 +3,18 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var CSharpHighlightRules = require("./csharp_highlight_rules").CSharpHighlightRules; var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; -var CStyleFoldMode = require("./folding/csharp").FoldMode; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = CSharpHighlightRules; + var highlighter = new CSharpHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); + this.$keywordList = highlighter.$keywordList; this.foldingRules = new CStyleFoldMode(); }; oop.inherits(Mode, TextMode); @@ -24,7 +27,7 @@ oop.inherits(Mode, TextMode); this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); - var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); var tokens = tokenizedLine.tokens; if (tokens.length && tokens[tokens.length-1].type == "comment") { @@ -54,7 +57,6 @@ oop.inherits(Mode, TextMode); return null; }; - this.$id = "ace/mode/csharp"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/csharp_highlight_rules.js b/lib/ace/mode/csharp_highlight_rules.js index 6e7ba5d4..c18be8ea 100644 --- a/lib/ace/mode/csharp_highlight_rules.js +++ b/lib/ace/mode/csharp_highlight_rules.js @@ -26,6 +26,9 @@ var CSharpHighlightRules = function() { token : "comment", // multi line comment regex : "\\/\\*", next : "comment" + }, { + token : "string.regexp", + regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)" }, { token : "string", // character regex : /'(?:.|\\(:?u[\da-fA-F]+|x[\da-fA-F]+|[tbrf'"n]))'/ @@ -53,9 +56,6 @@ var CSharpHighlightRules = function() { }, { token : "keyword.operator", regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" - }, { - token : "keyword", - regex : "^\\s*#(if|else|elif|endif|define|undef|warning|error|line|region|endregion|pragma)" }, { token : "punctuation.operator", regex : "\\?|\\:|\\,|\\;|\\." diff --git a/lib/ace/mode/css.js b/lib/ace/mode/css.js index 6fef5ccd..fcaa298c 100644 --- a/lib/ace/mode/css.js +++ b/lib/ace/mode/css.js @@ -33,6 +33,7 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var WorkerClient = require("../worker/worker_client").WorkerClient; @@ -40,9 +41,11 @@ var CssBehaviour = require("./behaviour/css").CssBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = CssHighlightRules; + var highlighter = new CssHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CssBehaviour(); + this.$keywordList = highlighter.$keywordList; this.foldingRules = new CStyleFoldMode(); }; oop.inherits(Mode, TextMode); @@ -56,7 +59,7 @@ oop.inherits(Mode, TextMode); var indent = this.$getIndent(line); // ignore braces in comments - var tokens = this.getTokenizer().getLineTokens(line, state).tokens; + var tokens = this.$tokenizer.getLineTokens(line, state).tokens; if (tokens.length && tokens[tokens.length-1].type == "comment") { return indent; } @@ -81,7 +84,7 @@ oop.inherits(Mode, TextMode); var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker"); worker.attachToDocument(session.getDocument()); - worker.on("annotate", function(e) { + worker.on("csslint", function(e) { session.setAnnotations(e.data); }); @@ -92,7 +95,6 @@ oop.inherits(Mode, TextMode); return worker; }; - this.$id = "ace/mode/css"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/css/csslint.js b/lib/ace/mode/css/csslint.js index c3c79a80..9f4c3bc8 100644 --- a/lib/ace/mode/css/csslint.js +++ b/lib/ace/mode/css/csslint.js @@ -1,10 +1,10 @@ define(function(require, exports, module) { /*! CSSLint -Copyright (c) 2014 Nicole Sullivan and Nicholas C. Zakas. All rights reserved. +Copyright (c) 2011 Nicole Sullivan and Nicholas C. Zakas. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the 'Software'), to deal +of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is @@ -13,7 +13,7 @@ furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Build: v0.10.0 22-July-2014 01:17:52 */ +/* Build time: 17-January-2013 10:55:01 */ /*! Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -46,10 +46,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v0.2.5, Build time: 7-May-2014 03:37:38 */ +/* Version v0.2.2, Build time: 17-January-2013 10:26:34 */ var parserlib = {}; (function(){ + /** * A generic base to inherit from for any object * that needs event handling. @@ -64,7 +65,7 @@ function EventTarget(){ * @property _listeners * @private */ - this._listeners = {}; + this._listeners = {}; } EventTarget.prototype = { @@ -86,14 +87,14 @@ EventTarget.prototype = { this._listeners[type].push(listener); }, - + /** * Fires an event based on the passed-in object. * @param {Object|String} event An object with at least a 'type' attribute * or a string indicating the event name. * @return {void} * @method fire - */ + */ fire: function(event){ if (typeof event == "string"){ event = { type: event }; @@ -101,19 +102,19 @@ EventTarget.prototype = { if (typeof event.target != "undefined"){ event.target = this; } - + if (typeof event.type == "undefined"){ throw new Error("Event object missing 'type' property."); } - + if (this._listeners[event.type]){ - + //create a copy of the array and use that so listeners can't chane var listeners = this._listeners[event.type].concat(); for (var i=0, len=listeners.length; i < len; i++){ listeners[i].call(this, event); } - } + } }, /** @@ -132,9 +133,9 @@ EventTarget.prototype = { break; } } - - - } + + + } } }; /** @@ -498,16 +499,16 @@ SyntaxUnit.prototype = { //restore constructor constructor: SyntaxUnit, - + /** * Returns the text representation of the unit. * @return {String} The text representation of the unit. * @method valueOf */ valueOf: function(){ - return this.text; + return this.toString(); }, - + /** * Returns the text representation of the unit. * @return {String} The text representation of the unit. @@ -525,7 +526,7 @@ SyntaxUnit.prototype = { * @class TokenStreamBase * @namespace parserlib.util * @constructor - * @param {String|StringReader} input The text to tokenize or a reader from + * @param {String|StringReader} input The text to tokenize or a reader from * which to read the input. */ function TokenStreamBase(input, tokenData){ @@ -537,15 +538,15 @@ function TokenStreamBase(input, tokenData){ * @private */ this._reader = input ? new StringReader(input.toString()) : null; - + /** * Token object for the last consumed token. * @type Token * @property _token * @private */ - this._token = null; - + this._token = null; + /** * The array of token information. * @type Array @@ -553,7 +554,7 @@ function TokenStreamBase(input, tokenData){ * @private */ this._tokenData = tokenData; - + /** * Lookahead token buffer. * @type Array @@ -561,7 +562,7 @@ function TokenStreamBase(input, tokenData){ * @private */ this._lt = []; - + /** * Lookahead token buffer index. * @type int @@ -569,7 +570,7 @@ function TokenStreamBase(input, tokenData){ * @private */ this._ltIndex = 0; - + this._ltIndexCache = []; } @@ -589,7 +590,7 @@ TokenStreamBase.createTokenData = function(tokens){ tokenData = tokens.concat([]), i = 0, len = tokenData.length+1; - + tokenData.UNKNOWN = -1; tokenData.unshift({name:"EOF"}); @@ -600,27 +601,27 @@ TokenStreamBase.createTokenData = function(tokens){ typeMap[tokenData[i].text] = i; } } - + tokenData.name = function(tt){ return nameMap[tt]; }; - + tokenData.type = function(c){ return typeMap[c]; }; - + return tokenData; }; TokenStreamBase.prototype = { //restore constructor - constructor: TokenStreamBase, - + constructor: TokenStreamBase, + //------------------------------------------------------------------------- // Matching methods //------------------------------------------------------------------------- - + /** * Determines if the next token matches the given token type. * If so, that token is consumed; if not, the token is placed @@ -636,27 +637,27 @@ TokenStreamBase.prototype = { * @method match */ match: function(tokenTypes, channel){ - + //always convert to an array, makes things easier if (!(tokenTypes instanceof Array)){ tokenTypes = [tokenTypes]; } - + var tt = this.get(channel), i = 0, len = tokenTypes.length; - + while(i < len){ if (tt == tokenTypes[i++]){ return true; } } - + //no match found, put the token back this.unget(); return false; - }, - + }, + /** * Determines if the next token matches the given token type. * If so, that token is consumed; if not, an error is thrown. @@ -667,7 +668,7 @@ TokenStreamBase.prototype = { * provided, reads from the default (unnamed) channel. * @return {void} * @method mustMatch - */ + */ mustMatch: function(tokenTypes, channel){ var token; @@ -677,17 +678,17 @@ TokenStreamBase.prototype = { tokenTypes = [tokenTypes]; } - if (!this.match.apply(this, arguments)){ + if (!this.match.apply(this, arguments)){ token = this.LT(1); - throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name + + throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name + " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); } }, - + //------------------------------------------------------------------------- // Consuming methods //------------------------------------------------------------------------- - + /** * Keeps reading from the token stream until either one of the specified * token types is found or until the end of the input is reached. @@ -700,21 +701,21 @@ TokenStreamBase.prototype = { * @method advance */ advance: function(tokenTypes, channel){ - + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ this.get(); } - return this.LA(0); + return this.LA(0); }, - + /** - * Consumes the next token from the token stream. + * Consumes the next token from the token stream. * @return {int} The token type of the token that was just consumed. * @method get - */ + */ get: function(channel){ - + var tokenInfo = this._tokenData, reader = this._reader, value, @@ -723,14 +724,14 @@ TokenStreamBase.prototype = { found = false, token, info; - + //check the lookahead buffer first - if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){ - + if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){ + i++; this._token = this._lt[this._ltIndex++]; info = tokenInfo[this._token.type]; - + //obey channels logic while((info.channel !== undefined && channel !== info.channel) && this._ltIndex < this._lt.length){ @@ -738,7 +739,7 @@ TokenStreamBase.prototype = { info = tokenInfo[this._token.type]; i++; } - + //here be dragons if ((info.channel === undefined || channel === info.channel) && this._ltIndex <= this._lt.length){ @@ -746,45 +747,45 @@ TokenStreamBase.prototype = { return this._token.type; } } - + //call token retriever method token = this._getToken(); //if it should be hidden, don't save a token if (token.type > -1 && !tokenInfo[token.type].hide){ - + //apply token channel token.channel = tokenInfo[token.type].channel; - + //save for later this._token = token; this._lt.push(token); //save space that will be moved (must be done before array is truncated) - this._ltIndexCache.push(this._lt.length - this._ltIndex + i); - + this._ltIndexCache.push(this._lt.length - this._ltIndex + i); + //keep the buffer under 5 items if (this._lt.length > 5){ - this._lt.shift(); + this._lt.shift(); } - + //also keep the shift buffer under 5 items if (this._ltIndexCache.length > 5){ this._ltIndexCache.shift(); } - + //update lookahead index this._ltIndex = this._lt.length; } - + /* * Skip to the next token if: * 1. The token type is marked as hidden. * 2. The token type has a channel specified and it isn't the current channel. */ info = tokenInfo[token.type]; - if (info && - (info.hide || + if (info && + (info.hide || (info.channel !== undefined && channel !== info.channel))){ return this.get(channel); } else { @@ -792,7 +793,7 @@ TokenStreamBase.prototype = { return token.type; } }, - + /** * Looks ahead a certain number of tokens and returns the token type at * that position. This will throw an error if you lookahead past the @@ -811,34 +812,34 @@ TokenStreamBase.prototype = { if (index > 5){ throw new Error("Too much lookahead."); } - + //get all those tokens while(total){ - tt = this.get(); - total--; + tt = this.get(); + total--; } - + //unget all those tokens while(total < index){ this.unget(); total++; } } else if (index < 0){ - + if(this._lt[this._ltIndex+index]){ tt = this._lt[this._ltIndex+index].type; } else { throw new Error("Too much lookbehind."); } - + } else { tt = this._token.type; } - + return tt; - + }, - + /** * Looks ahead a certain number of tokens and returns the token at * that position. This will throw an error if you lookahead past the @@ -848,18 +849,18 @@ TokenStreamBase.prototype = { * current token, 1 for the next, -1 for the previous, etc. * @return {Object} The token of the token in the given position. * @method LA - */ + */ LT: function(index){ - + //lookahead first to prime the token buffer this.LA(index); - + //now find the token, subtract one because _ltIndex is already at the next index - return this._lt[this._ltIndex+index-1]; + return this._lt[this._ltIndex+index-1]; }, - + /** - * Returns the token type for the next token in the stream without + * Returns the token type for the next token in the stream without * consuming it. * @return {int} The token type of the next token in the stream. * @method peek @@ -867,7 +868,7 @@ TokenStreamBase.prototype = { peek: function(){ return this.LA(1); }, - + /** * Returns the actual token object for the last consumed token. * @return {Token} The token object for the last consumed token. @@ -876,7 +877,7 @@ TokenStreamBase.prototype = { token: function(){ return this._token; }, - + /** * Returns the name of the token for the given token type. * @param {int} tokenType The type of token to get the name of. @@ -891,22 +892,22 @@ TokenStreamBase.prototype = { return this._tokenData[tokenType].name; } }, - + /** * Returns the token type value for the given token name. * @param {String} tokenName The name of the token whose value should be returned. * @return {int} The token type value for the given token name or -1 * for an unknown token. * @method tokenName - */ + */ tokenType: function(tokenName){ return this._tokenData[tokenName] || -1; }, - + /** * Returns the last consumed token to the token stream. * @method unget - */ + */ unget: function(){ //if (this._ltIndex > -1){ if (this._ltIndexCache.length){ @@ -920,6 +921,8 @@ TokenStreamBase.prototype = { }; + + parserlib.util = { StringReader: StringReader, SyntaxError : SyntaxError, @@ -928,6 +931,8 @@ EventTarget : EventTarget, TokenStreamBase : TokenStreamBase }; })(); + + /* Parser-Lib Copyright (c) 2009-2011 Nicholas C. Zakas. All rights reserved. @@ -951,7 +956,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* Version v0.2.5, Build time: 7-May-2014 03:37:38 */ +/* Version v0.2.2, Build time: 17-January-2013 10:26:34 */ (function(){ var EventTarget = parserlib.util.EventTarget, TokenStreamBase = parserlib.util.TokenStreamBase, @@ -959,6 +964,7 @@ StringReader = parserlib.util.StringReader, SyntaxError = parserlib.util.SyntaxError, SyntaxUnit = parserlib.util.SyntaxUnit; + var Colors = { aliceblue :"#f0f8ff", antiquewhite :"#faebd7", @@ -985,7 +991,6 @@ var Colors = { darkcyan :"#008b8b", darkgoldenrod :"#b8860b", darkgray :"#a9a9a9", - darkgrey :"#a9a9a9", darkgreen :"#006400", darkkhaki :"#bdb76b", darkmagenta :"#8b008b", @@ -997,13 +1002,11 @@ var Colors = { darkseagreen :"#8fbc8f", darkslateblue :"#483d8b", darkslategray :"#2f4f4f", - darkslategrey :"#2f4f4f", darkturquoise :"#00ced1", darkviolet :"#9400d3", deeppink :"#ff1493", deepskyblue :"#00bfff", dimgray :"#696969", - dimgrey :"#696969", dodgerblue :"#1e90ff", firebrick :"#b22222", floralwhite :"#fffaf0", @@ -1014,7 +1017,6 @@ var Colors = { gold :"#ffd700", goldenrod :"#daa520", gray :"#808080", - grey :"#808080", green :"#008000", greenyellow :"#adff2f", honeydew :"#f0fff0", @@ -1032,14 +1034,12 @@ var Colors = { lightcyan :"#e0ffff", lightgoldenrodyellow :"#fafad2", lightgray :"#d3d3d3", - lightgrey :"#d3d3d3", lightgreen :"#90ee90", lightpink :"#ffb6c1", lightsalmon :"#ffa07a", lightseagreen :"#20b2aa", lightskyblue :"#87cefa", lightslategray :"#778899", - lightslategrey :"#778899", lightsteelblue :"#b0c4de", lightyellow :"#ffffe0", lime :"#00ff00", @@ -1092,7 +1092,6 @@ var Colors = { skyblue :"#87ceeb", slateblue :"#6a5acd", slategray :"#708090", - slategrey :"#708090", snow :"#fffafa", springgreen :"#00ff7f", steelblue :"#4682b4", @@ -1118,7 +1117,6 @@ var Colors = { buttontext :"Text on push buttons.", captiontext :"Text in caption, size box, and scrollbar arrow box.", graytext :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.", - greytext :"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.", highlight :"Item(s) selected in a control.", highlighttext :"Text of item(s) selected in a control.", inactiveborder :"Inactive window border.", @@ -1145,12 +1143,12 @@ var Colors = { * @class Combinator * @extends parserlib.util.SyntaxUnit * @constructor - * @param {String} text The text representation of the unit. + * @param {String} text The text representation of the unit. * @param {int} line The line of text on which the unit resides. * @param {int} col The column of text on which the unit resides. */ function Combinator(text, line, col){ - + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); /** @@ -1159,7 +1157,7 @@ function Combinator(text, line, col){ * @property type */ this.type = "unknown"; - + //pretty simple if (/^\s+$/.test(text)){ this.type = "descendant"; @@ -1176,6 +1174,7 @@ function Combinator(text, line, col){ Combinator.prototype = new SyntaxUnit(); Combinator.prototype.constructor = Combinator; + /*global SyntaxUnit, Parser*/ /** * Represents a media feature, such as max-width:500. @@ -1187,7 +1186,7 @@ Combinator.prototype.constructor = Combinator; * @param {SyntaxUnit} value The value of the feature or null if none. */ function MediaFeature(name, value){ - + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); /** @@ -1208,6 +1207,7 @@ function MediaFeature(name, value){ MediaFeature.prototype = new SyntaxUnit(); MediaFeature.prototype.constructor = MediaFeature; + /*global SyntaxUnit, Parser*/ /** * Represents an individual media query. @@ -1222,8 +1222,8 @@ MediaFeature.prototype.constructor = MediaFeature; * @param {int} col The column of text on which the unit resides. */ function MediaQuery(modifier, mediaType, features, line, col){ - - SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); + + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); /** * The media modifier ("not" or "only") @@ -1237,8 +1237,8 @@ function MediaQuery(modifier, mediaType, features, line, col){ * @type String * @property mediaType */ - this.mediaType = mediaType; - + this.mediaType = mediaType; + /** * The parts that make up the selector. * @type Array @@ -1251,6 +1251,7 @@ function MediaQuery(modifier, mediaType, features, line, col){ MediaQuery.prototype = new SyntaxUnit(); MediaQuery.prototype.constructor = MediaQuery; + /*global Tokens, TokenStream, SyntaxError, Properties, Validation, ValidationError, SyntaxUnit, PropertyValue, PropertyValuePart, SelectorPart, SelectorSubPart, Selector, PropertyName, Combinator, MediaFeature, MediaQuery, EventTarget */ @@ -1295,10 +1296,10 @@ Parser.prototype = function(){ var proto = new EventTarget(), //new prototype prop, additions = { - + //restore constructor constructor: Parser, - + //instance constants - yuck DEFAULT_TYPE : 0, COMBINATOR_TYPE : 1, @@ -1309,14 +1310,14 @@ Parser.prototype = function(){ PROPERTY_VALUE_PART_TYPE : 6, SELECTOR_TYPE : 7, SELECTOR_PART_TYPE : 8, - SELECTOR_SUB_PART_TYPE : 9, - + SELECTOR_SUB_PART_TYPE : 9, + //----------------------------------------------------------------- // Grammar //----------------------------------------------------------------- - + _stylesheet: function(){ - + /* * stylesheet * : [ CHARSET_SYM S* STRING S* ';' ]? @@ -1324,19 +1325,19 @@ Parser.prototype = function(){ * [ namespace [S|CDO|CDC]* ]* * [ [ ruleset | media | page | font_face | keyframes ] [S|CDO|CDC]* ]* * ; - */ - + */ + var tokenStream = this._tokenStream, charset = null, count, token, tt; - + this.fire("startstylesheet"); - + //try to read character set this._charset(); - + this._skipCruft(); //try to read imports - may be more than one @@ -1344,46 +1345,42 @@ Parser.prototype = function(){ this._import(); this._skipCruft(); } - + //try to read namespaces - may be more than one while (tokenStream.peek() == Tokens.NAMESPACE_SYM){ this._namespace(); this._skipCruft(); } - + //get the next token tt = tokenStream.peek(); - + //try to read the rest while(tt > Tokens.EOF){ - + try { - + switch(tt){ case Tokens.MEDIA_SYM: this._media(); this._skipCruft(); break; case Tokens.PAGE_SYM: - this._page(); + this._page(); this._skipCruft(); - break; + break; case Tokens.FONT_FACE_SYM: - this._font_face(); + this._font_face(); this._skipCruft(); - break; + break; case Tokens.KEYFRAMES_SYM: - this._keyframes(); + this._keyframes(); this._skipCruft(); - break; - case Tokens.VIEWPORT_SYM: - this._viewport(); - this._skipCruft(); - break; + break; case Tokens.UNKNOWN_SYM: //unknown @ rule tokenStream.get(); if (!this.options.strict){ - + //fire error event this.fire({ type: "error", @@ -1391,30 +1388,30 @@ Parser.prototype = function(){ message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", line: tokenStream.LT(0).startLine, col: tokenStream.LT(0).startCol - }); - + }); + //skip braces count=0; while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ count++; //keep track of nesting depth } - + while(count){ tokenStream.advance([Tokens.RBRACE]); count--; } - + } else { //not a syntax error, rethrow it throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); - } + } break; case Tokens.S: this._readWhitespace(); break; - default: + default: if(!this._ruleset()){ - + //error handling for known issues switch(tt){ case Tokens.CHARSET_SYM: @@ -1433,7 +1430,7 @@ Parser.prototype = function(){ tokenStream.get(); //get the last token this._unexpectedToken(tokenStream.token()); } - + } } } catch(ex) { @@ -1444,84 +1441,84 @@ Parser.prototype = function(){ message: ex.message, line: ex.line, col: ex.col - }); + }); } else { throw ex; } } - + tt = tokenStream.peek(); } - + if (tt != Tokens.EOF){ this._unexpectedToken(tokenStream.token()); } - + this.fire("endstylesheet"); }, - + _charset: function(emit){ var tokenStream = this._tokenStream, charset, token, line, col; - + if (tokenStream.match(Tokens.CHARSET_SYM)){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; - + this._readWhitespace(); tokenStream.mustMatch(Tokens.STRING); - + token = tokenStream.token(); charset = token.value; - + this._readWhitespace(); tokenStream.mustMatch(Tokens.SEMICOLON); - + if (emit !== false){ - this.fire({ + this.fire({ type: "charset", charset:charset, line: line, col: col }); } - } + } }, - + _import: function(emit){ /* * import * : IMPORT_SYM S* * [STRING|URI] S* media_query_list? ';' S* - */ - + */ + var tokenStream = this._tokenStream, tt, uri, importToken, mediaList = []; - + //read import symbol tokenStream.mustMatch(Tokens.IMPORT_SYM); importToken = tokenStream.token(); this._readWhitespace(); - + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); - + //grab the URI value - uri = tokenStream.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/, "$1"); + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); this._readWhitespace(); - + mediaList = this._media_query_list(); - + //must end with a semicolon tokenStream.mustMatch(Tokens.SEMICOLON); this._readWhitespace(); - + if (emit !== false){ this.fire({ type: "import", @@ -1531,47 +1528,47 @@ Parser.prototype = function(){ col: importToken.startCol }); } - + }, - + _namespace: function(emit){ /* * namespace * : NAMESPACE_SYM S* [namespace_prefix S*]? [STRING|URI] S* ';' S* - */ - + */ + var tokenStream = this._tokenStream, line, col, prefix, uri; - + //read import symbol tokenStream.mustMatch(Tokens.NAMESPACE_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; this._readWhitespace(); - + //it's a namespace prefix - no _namespace_prefix() method because it's just an IDENT if (tokenStream.match(Tokens.IDENT)){ prefix = tokenStream.token().value; this._readWhitespace(); } - + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); /*if (!tokenStream.match(Tokens.STRING)){ tokenStream.mustMatch(Tokens.URI); }*/ - + //grab the URI value - uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); this._readWhitespace(); //must end with a semicolon tokenStream.mustMatch(Tokens.SEMICOLON); this._readWhitespace(); - + if (emit !== false){ this.fire({ type: "namespace", @@ -1581,9 +1578,9 @@ Parser.prototype = function(){ col: col }); } - - }, - + + }, + _media: function(){ /* * media @@ -1594,49 +1591,45 @@ Parser.prototype = function(){ line, col, mediaList;// = []; - + //look for @media tokenStream.mustMatch(Tokens.MEDIA_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; - - this._readWhitespace(); + + this._readWhitespace(); mediaList = this._media_query_list(); tokenStream.mustMatch(Tokens.LBRACE); this._readWhitespace(); - + this.fire({ type: "startmedia", media: mediaList, line: line, col: col }); - + while(true) { if (tokenStream.peek() == Tokens.PAGE_SYM){ this._page(); - } else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){ - this._font_face(); - } else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){ - this._viewport(); } else if (!this._ruleset()){ break; - } + } } - + tokenStream.mustMatch(Tokens.RBRACE); this._readWhitespace(); - + this.fire({ type: "endmedia", media: mediaList, line: line, col: col }); - }, - + }, + //CSS3 Media Queries _media_query_list: function(){ @@ -1647,26 +1640,26 @@ Parser.prototype = function(){ */ var tokenStream = this._tokenStream, mediaList = []; - - + + this._readWhitespace(); - + if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){ mediaList.push(this._media_query()); } - + while(tokenStream.match(Tokens.COMMA)){ this._readWhitespace(); mediaList.push(this._media_query()); } - + return mediaList; }, - + /* * Note: "expression" in the grammar maps to the _media_expression * method. - + */ _media_query: function(){ /* @@ -1680,10 +1673,10 @@ Parser.prototype = function(){ ident = null, token = null, expressions = []; - + if (tokenStream.match(Tokens.IDENT)){ ident = tokenStream.token().value.toLowerCase(); - + //since there's no custom tokens for these, need to manually check if (ident != "only" && ident != "not"){ tokenStream.unget(); @@ -1692,9 +1685,9 @@ Parser.prototype = function(){ token = tokenStream.token(); } } - + this._readWhitespace(); - + if (tokenStream.peek() == Tokens.IDENT){ type = this._media_type(); if (token === null){ @@ -1705,17 +1698,17 @@ Parser.prototype = function(){ token = tokenStream.LT(1); } expressions.push(this._media_expression()); - } - + } + if (type === null && expressions.length === 0){ return null; - } else { + } else { this._readWhitespace(); while (tokenStream.match(Tokens.IDENT)){ if (tokenStream.token().value.toLowerCase() != "and"){ this._unexpectedToken(tokenStream.token()); } - + this._readWhitespace(); expressions.push(this._media_expression()); } @@ -1731,7 +1724,7 @@ Parser.prototype = function(){ * : IDENT * ; */ - return this._media_feature(); + return this._media_feature(); }, /** @@ -1752,22 +1745,22 @@ Parser.prototype = function(){ feature = null, token, expression = null; - + tokenStream.mustMatch(Tokens.LPAREN); - + feature = this._media_feature(); this._readWhitespace(); - + if (tokenStream.match(Tokens.COLON)){ this._readWhitespace(); token = tokenStream.LT(1); expression = this._expression(); } - + tokenStream.mustMatch(Tokens.RPAREN); this._readWhitespace(); - return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null)); + return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null)); }, //CSS3 Media Queries @@ -1778,33 +1771,33 @@ Parser.prototype = function(){ * ; */ var tokenStream = this._tokenStream; - + tokenStream.mustMatch(Tokens.IDENT); - - return SyntaxUnit.fromToken(tokenStream.token()); + + return SyntaxUnit.fromToken(tokenStream.token()); }, - + //CSS3 Paged Media _page: function(){ /* * page: - * PAGE_SYM S* IDENT? pseudo_page? S* + * PAGE_SYM S* IDENT? pseudo_page? S* * '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S* * ; - */ + */ var tokenStream = this._tokenStream, line, col, identifier = null, pseudoPage = null; - + //look for @page tokenStream.mustMatch(Tokens.PAGE_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; - + this._readWhitespace(); - + if (tokenStream.match(Tokens.IDENT)){ identifier = tokenStream.token().value; @@ -1812,35 +1805,35 @@ Parser.prototype = function(){ if (identifier.toLowerCase() === "auto"){ this._unexpectedToken(tokenStream.token()); } - } - + } + //see if there's a colon upcoming if (tokenStream.peek() == Tokens.COLON){ pseudoPage = this._pseudo_page(); } - + this._readWhitespace(); - + this.fire({ type: "startpage", id: identifier, pseudo: pseudoPage, line: line, col: col - }); - - this._readDeclarations(true, true); + }); + this._readDeclarations(true, true); + this.fire({ type: "endpage", id: identifier, pseudo: pseudoPage, line: line, col: col - }); - + }); + }, - + //CSS3 Paged Media _margin: function(){ /* @@ -1856,14 +1849,14 @@ Parser.prototype = function(){ if (marginSym){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; - + this.fire({ type: "startpagemargin", margin: marginSym, line: line, col: col - }); - + }); + this._readDeclarations(true); this.fire({ @@ -1871,7 +1864,7 @@ Parser.prototype = function(){ margin: marginSym, line: line, col: col - }); + }); return true; } else { return false; @@ -1880,17 +1873,17 @@ Parser.prototype = function(){ //CSS3 Paged Media _margin_sym: function(){ - + /* * margin_sym : - * TOPLEFTCORNER_SYM | - * TOPLEFT_SYM | - * TOPCENTER_SYM | - * TOPRIGHT_SYM | + * TOPLEFTCORNER_SYM | + * TOPLEFT_SYM | + * TOPCENTER_SYM | + * TOPRIGHT_SYM | * TOPRIGHTCORNER_SYM | - * BOTTOMLEFTCORNER_SYM | - * BOTTOMLEFT_SYM | - * BOTTOMCENTER_SYM | + * BOTTOMLEFTCORNER_SYM | + * BOTTOMLEFT_SYM | + * BOTTOMCENTER_SYM | * BOTTOMRIGHT_SYM | * BOTTOMRIGHTCORNER_SYM | * LEFTTOP_SYM | @@ -1898,178 +1891,145 @@ Parser.prototype = function(){ * LEFTBOTTOM_SYM | * RIGHTTOP_SYM | * RIGHTMIDDLE_SYM | - * RIGHTBOTTOM_SYM + * RIGHTBOTTOM_SYM * ; */ - + var tokenStream = this._tokenStream; - + if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM, Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM, - Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, + Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM, - Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, + Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM, Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM])) { - return SyntaxUnit.fromToken(tokenStream.token()); + return SyntaxUnit.fromToken(tokenStream.token()); } else { return null; } - + }, - + _pseudo_page: function(){ /* * pseudo_page * : ':' IDENT - * ; + * ; */ - + var tokenStream = this._tokenStream; - + tokenStream.mustMatch(Tokens.COLON); tokenStream.mustMatch(Tokens.IDENT); - + //TODO: CSS3 Paged Media says only "left", "center", and "right" are allowed - + return tokenStream.token().value; }, - + _font_face: function(){ /* * font_face - * : FONT_FACE_SYM S* + * : FONT_FACE_SYM S* * '{' S* declaration [ ';' S* declaration ]* '}' S* * ; - */ + */ var tokenStream = this._tokenStream, line, col; - + //look for @page tokenStream.mustMatch(Tokens.FONT_FACE_SYM); line = tokenStream.token().startLine; col = tokenStream.token().startCol; - + this._readWhitespace(); this.fire({ type: "startfontface", line: line, col: col - }); - + }); + this._readDeclarations(true); - + this.fire({ type: "endfontface", line: line, col: col - }); - }, - - _viewport: function(){ - /* - * viewport - * : VIEWPORT_SYM S* - * '{' S* declaration? [ ';' S* declaration? ]* '}' S* - * ; - */ - var tokenStream = this._tokenStream, - line, - col; - - tokenStream.mustMatch(Tokens.VIEWPORT_SYM); - line = tokenStream.token().startLine; - col = tokenStream.token().startCol; - - this._readWhitespace(); - - this.fire({ - type: "startviewport", - line: line, - col: col - }); - - this._readDeclarations(true); - - this.fire({ - type: "endviewport", - line: line, - col: col - }); - + }); }, _operator: function(inFunction){ - + /* * operator (outside function) * : '/' S* | ',' S* | /( empty )/ * operator (inside function) * : '/' S* | '+' S* | '*' S* | '-' S* /( empty )/ * ; - */ - + */ + var tokenStream = this._tokenStream, token = null; - + if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) || (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){ token = tokenStream.token(); this._readWhitespace(); - } + } return token ? PropertyValuePart.fromToken(token) : null; - + }, - + _combinator: function(){ - + /* * combinator * : PLUS S* | GREATER S* | TILDE S* | S+ * ; - */ - + */ + var tokenStream = this._tokenStream, value = null, token; - - if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){ + + if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){ token = tokenStream.token(); value = new Combinator(token.value, token.startLine, token.startCol); this._readWhitespace(); } - + return value; }, - + _unary_operator: function(){ - + /* * unary_operator * : '-' | '+' * ; */ - + var tokenStream = this._tokenStream; - + if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){ return tokenStream.token().value; } else { return null; - } + } }, - + _property: function(){ - + /* * property * : IDENT S* - * ; + * ; */ - + var tokenStream = this._tokenStream, value = null, hack = null, @@ -2077,7 +2037,7 @@ Parser.prototype = function(){ token, line, col; - + //check for star hack - throws error if not allowed if (tokenStream.peek() == Tokens.STAR && this.options.starHack){ tokenStream.get(); @@ -2086,33 +2046,33 @@ Parser.prototype = function(){ line = token.startLine; col = token.startCol; } - + if(tokenStream.match(Tokens.IDENT)){ token = tokenStream.token(); tokenValue = token.value; - + //check for underscore hack - no error if not allowed because it's valid CSS syntax if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){ hack = "_"; tokenValue = tokenValue.substring(1); } - + value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol)); this._readWhitespace(); } - + return value; }, - + //Augmented with CSS3 Selectors _ruleset: function(){ /* * ruleset * : selectors_group * '{' S* declaration? [ ';' S* declaration? ]* '}' S* - * ; - */ - + * ; + */ + var tokenStream = this._tokenStream, tt, selectors; @@ -2126,7 +2086,7 @@ Parser.prototype = function(){ selectors = this._selectors_group(); } catch (ex){ if (ex instanceof SyntaxError && !this.options.strict){ - + //fire error event this.fire({ type: "error", @@ -2134,8 +2094,8 @@ Parser.prototype = function(){ message: ex.message, line: ex.line, col: ex.col - }); - + }); + //skip over everything until closing brace tt = tokenStream.advance([Tokens.RBRACE]); if (tt == Tokens.RBRACE){ @@ -2143,57 +2103,57 @@ Parser.prototype = function(){ } else { //otherwise, rethrow the error because it wasn't handled properly throw ex; - } - + } + } else { //not a syntax error, rethrow it throw ex; - } - + } + //trigger parser to continue return true; } - + //if it got here, all selectors parsed - if (selectors){ - + if (selectors){ + this.fire({ type: "startrule", selectors: selectors, line: selectors[0].line, col: selectors[0].col - }); - - this._readDeclarations(true); - + }); + + this._readDeclarations(true); + this.fire({ type: "endrule", selectors: selectors, line: selectors[0].line, col: selectors[0].col - }); - + }); + } - + return selectors; - + }, //CSS3 Selectors _selectors_group: function(){ - - /* + + /* * selectors_group * : selector [ COMMA S* selector ]* * ; - */ + */ var tokenStream = this._tokenStream, selectors = [], selector; - + selector = this._selector(); if (selector !== null){ - + selectors.push(selector); while(tokenStream.match(Tokens.COMMA)){ this._readWhitespace(); @@ -2208,83 +2168,83 @@ Parser.prototype = function(){ return selectors.length ? selectors : null; }, - + //CSS3 Selectors _selector: function(){ /* * selector * : simple_selector_sequence [ combinator simple_selector_sequence ]* - * ; + * ; */ - + var tokenStream = this._tokenStream, selector = [], nextSelector = null, combinator = null, ws = null; - + //if there's no simple selector, then there's no selector nextSelector = this._simple_selector_sequence(); if (nextSelector === null){ return null; } - + selector.push(nextSelector); - + do { - + //look for a combinator combinator = this._combinator(); - + if (combinator !== null){ selector.push(combinator); nextSelector = this._simple_selector_sequence(); - + //there must be a next selector if (nextSelector === null){ this._unexpectedToken(tokenStream.LT(1)); } else { - + //nextSelector is an instance of SelectorPart selector.push(nextSelector); } } else { - + //if there's not whitespace, we're done - if (this._readWhitespace()){ - + if (this._readWhitespace()){ + //add whitespace separator ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol); - + //combinator is not required combinator = this._combinator(); - + //selector is required if there's a combinator nextSelector = this._simple_selector_sequence(); - if (nextSelector === null){ + if (nextSelector === null){ if (combinator !== null){ this._unexpectedToken(tokenStream.LT(1)); } } else { - + if (combinator !== null){ selector.push(combinator); } else { selector.push(ws); } - + selector.push(nextSelector); - } + } } else { break; - } - + } + } } while(true); - + return new Selector(selector, selector[0].line, selector[0].col); }, - + //CSS3 Selectors _simple_selector_sequence: function(){ /* @@ -2294,13 +2254,13 @@ Parser.prototype = function(){ * | [ HASH | class | attrib | pseudo | negation ]+ * ; */ - + var tokenStream = this._tokenStream, - + //parts of a simple selector elementName = null, modifiers = [], - + //complete selector text selectorText= "", @@ -2323,35 +2283,35 @@ Parser.prototype = function(){ found = false, line, col; - - + + //get starting line and column for the selector line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol; - + elementName = this._type_selector(); if (!elementName){ elementName = this._universal(); } - + if (elementName !== null){ selectorText += elementName; - } - + } + while(true){ //whitespace means we're done if (tokenStream.peek() === Tokens.S){ break; } - + //check for each component while(i < len && component === null){ component = components[i++].call(this); } - + if (component === null){ - + //we don't have a selector if (selectorText === ""){ return null; @@ -2361,17 +2321,17 @@ Parser.prototype = function(){ } else { i = 0; modifiers.push(component); - selectorText += component.toString(); + selectorText += component.toString(); component = null; } } - + return selectorText !== "" ? new SelectorPart(elementName, modifiers, selectorText, line, col) : null; - }, - + }, + //CSS3 Selectors _type_selector: function(){ /* @@ -2379,12 +2339,12 @@ Parser.prototype = function(){ * : [ namespace_prefix ]? element_name * ; */ - + var tokenStream = this._tokenStream, ns = this._namespace_prefix(), elementName = this._element_name(); - - if (!elementName){ + + if (!elementName){ /* * Need to back out the namespace that was read due to both * type_selector and universal reading namespace_prefix @@ -2397,9 +2357,9 @@ Parser.prototype = function(){ tokenStream.unget(); } } - + return null; - } else { + } else { if (ns){ elementName.text = ns + elementName.text; elementName.col -= ns.length; @@ -2407,97 +2367,97 @@ Parser.prototype = function(){ return elementName; } }, - + //CSS3 Selectors _class: function(){ /* * class * : '.' IDENT * ; - */ - + */ + var tokenStream = this._tokenStream, token; - + if (tokenStream.match(Tokens.DOT)){ - tokenStream.mustMatch(Tokens.IDENT); + tokenStream.mustMatch(Tokens.IDENT); token = tokenStream.token(); - return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1); + return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1); } else { return null; } - + }, - + //CSS3 Selectors _element_name: function(){ /* * element_name * : IDENT * ; - */ - + */ + var tokenStream = this._tokenStream, token; - + if (tokenStream.match(Tokens.IDENT)){ token = tokenStream.token(); - return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol); - + return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol); + } else { return null; } }, - + //CSS3 Selectors _namespace_prefix: function(){ - /* + /* * namespace_prefix * : [ IDENT | '*' ]? '|' * ; */ var tokenStream = this._tokenStream, value = ""; - + //verify that this is a namespace prefix if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){ - + if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){ value += tokenStream.token().value; } - + tokenStream.mustMatch(Tokens.PIPE); value += "|"; - + } - - return value.length ? value : null; + + return value.length ? value : null; }, - + //CSS3 Selectors _universal: function(){ /* * universal * : [ namespace_prefix ]? '*' - * ; + * ; */ var tokenStream = this._tokenStream, value = "", ns; - + ns = this._namespace_prefix(); if(ns){ value += ns; } - + if(tokenStream.match(Tokens.STAR)){ value += "*"; } - + return value.length ? value : null; - + }, - + //CSS3 Selectors _attrib: function(){ /* @@ -2510,69 +2470,69 @@ Parser.prototype = function(){ * INCLUDES | * DASHMATCH ] S* [ IDENT | STRING ] S* * ]? ']' - * ; + * ; */ - + var tokenStream = this._tokenStream, value = null, ns, token; - + if (tokenStream.match(Tokens.LBRACKET)){ token = tokenStream.token(); value = token.value; value += this._readWhitespace(); - + ns = this._namespace_prefix(); - + if (ns){ value += ns; } - + tokenStream.mustMatch(Tokens.IDENT); - value += tokenStream.token().value; + value += tokenStream.token().value; value += this._readWhitespace(); - + if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH, Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){ - - value += tokenStream.token().value; + + value += tokenStream.token().value; value += this._readWhitespace(); - + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); - value += tokenStream.token().value; + value += tokenStream.token().value; value += this._readWhitespace(); } - + tokenStream.mustMatch(Tokens.RBRACKET); - + return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol); } else { return null; } }, - + //CSS3 Selectors _pseudo: function(){ - + /* * pseudo * : ':' ':'? [ IDENT | functional_pseudo ] - * ; - */ - + * ; + */ + var tokenStream = this._tokenStream, pseudo = null, colons = ":", line, col; - + if (tokenStream.match(Tokens.COLON)){ - + if (tokenStream.match(Tokens.COLON)){ colons += ":"; } - + if (tokenStream.match(Tokens.IDENT)){ pseudo = tokenStream.token().value; line = tokenStream.token().startLine; @@ -2582,26 +2542,26 @@ Parser.prototype = function(){ col = tokenStream.LT(1).startCol - colons.length; pseudo = this._functional_pseudo(); } - + if (pseudo){ pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col); } } - + return pseudo; }, - + //CSS3 Selectors _functional_pseudo: function(){ /* * functional_pseudo * : FUNCTION S* expression ')' * ; - */ - + */ + var tokenStream = this._tokenStream, value = null; - + if(tokenStream.match(Tokens.FUNCTION)){ value = tokenStream.token().value; value += this._readWhitespace(); @@ -2609,10 +2569,10 @@ Parser.prototype = function(){ tokenStream.mustMatch(Tokens.RPAREN); value += ")"; } - + return value; }, - + //CSS3 Selectors _expression: function(){ /* @@ -2620,26 +2580,26 @@ Parser.prototype = function(){ * : [ [ PLUS | '-' | DIMENSION | NUMBER | STRING | IDENT ] S* ]+ * ; */ - + var tokenStream = this._tokenStream, value = ""; - + while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION, Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH, Tokens.FREQ, Tokens.ANGLE, Tokens.TIME, Tokens.RESOLUTION, Tokens.SLASH])){ - + value += tokenStream.token().value; - value += this._readWhitespace(); + value += this._readWhitespace(); } - + return value.length ? value : null; - + }, //CSS3 Selectors _negation: function(){ - /* + /* * negation * : NOT S* negation_arg S* ')' * ; @@ -2651,7 +2611,7 @@ Parser.prototype = function(){ value = "", arg, subpart = null; - + if (tokenStream.match(Tokens.NOT)){ value = tokenStream.token().value; line = tokenStream.token().startLine; @@ -2662,22 +2622,22 @@ Parser.prototype = function(){ value += this._readWhitespace(); tokenStream.match(Tokens.RPAREN); value += tokenStream.token().value; - + subpart = new SelectorSubPart(value, "not", line, col); subpart.args.push(arg); } - + return subpart; }, - + //CSS3 Selectors - _negation_arg: function(){ + _negation_arg: function(){ /* * negation_arg * : type_selector | universal | HASH | class | attrib | pseudo - * ; - */ - + * ; + */ + var tokenStream = this._tokenStream, args = [ this._type_selector, @@ -2685,11 +2645,11 @@ Parser.prototype = function(){ function(){ return tokenStream.match(Tokens.HASH) ? new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : - null; + null; }, this._class, this._attrib, - this._pseudo + this._pseudo ], arg = null, i = 0, @@ -2698,40 +2658,40 @@ Parser.prototype = function(){ line, col, part; - + line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol; - + while(i < len && arg === null){ - + arg = args[i].call(this); i++; } - + //must be a negation arg if (arg === null){ this._unexpectedToken(tokenStream.LT(1)); } - + //it's an element name if (arg.type == "elementName"){ part = new SelectorPart(arg, [], arg.toString(), line, col); } else { part = new SelectorPart(null, [arg], arg.toString(), line, col); } - - return part; + + return part; }, - + _declaration: function(){ - + /* * declaration * : property ':' S* expr prio? * | /( empty )/ - * ; - */ - + * ; + */ + var tokenStream = this._tokenStream, property = null, expr = null, @@ -2739,22 +2699,22 @@ Parser.prototype = function(){ error = null, invalid = null, propertyName= ""; - + property = this._property(); if (property !== null){ tokenStream.mustMatch(Tokens.COLON); this._readWhitespace(); - + expr = this._expr(); - + //if there's no parts for the value, it's an error if (!expr || expr.length === 0){ this._unexpectedToken(tokenStream.LT(1)); } - + prio = this._prio(); - + /* * If hacks should be allowed, then only check the root * property. If hacks should not be allowed, treat @@ -2763,16 +2723,16 @@ Parser.prototype = function(){ propertyName = property.toString(); if (this.options.starHack && property.hack == "*" || this.options.underscoreHack && property.hack == "_") { - + propertyName = property.text; } - + try { this._validateProperty(propertyName, expr); } catch (ex) { invalid = ex; } - + this.fire({ type: "property", property: property, @@ -2781,46 +2741,46 @@ Parser.prototype = function(){ line: property.line, col: property.col, invalid: invalid - }); - + }); + return true; } else { return false; } }, - + _prio: function(){ /* * prio * : IMPORTANT_SYM S* - * ; + * ; */ - + var tokenStream = this._tokenStream, result = tokenStream.match(Tokens.IMPORTANT_SYM); - + this._readWhitespace(); return result; }, - + _expr: function(inFunction){ /* * expr * : term [ operator term ]* * ; */ - + var tokenStream = this._tokenStream, values = [], //valueParts = [], value = null, operator = null; - - value = this._term(inFunction); + + value = this._term(); if (value !== null){ - + values.push(value); - + do { operator = this._operator(inFunction); @@ -2832,9 +2792,9 @@ Parser.prototype = function(){ values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); valueParts = []; }*/ - - value = this._term(inFunction); - + + value = this._term(); + if (value === null){ break; } else { @@ -2842,17 +2802,17 @@ Parser.prototype = function(){ } } while(true); } - + //cleanup /*if (valueParts.length){ values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); }*/ - + return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null; }, - - _term: function(inFunction){ - + + _term: function(){ + /* * term * : unary_operator? @@ -2860,51 +2820,36 @@ Parser.prototype = function(){ * TIME S* | FREQ S* | function | ie_function ] * | STRING S* | IDENT S* | URI S* | UNICODERANGE S* | hexcolor * ; - */ - + */ + var tokenStream = this._tokenStream, unary = null, value = null, - endChar = null, token, line, col; - + //returns the operator or null unary = this._unary_operator(); if (unary !== null){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; - } - + } + //exception for IE filters if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){ - + value = this._ie_function(); if (unary === null){ line = tokenStream.token().startLine; col = tokenStream.token().startCol; } - - //see if it's a simple block - } else if (inFunction && tokenStream.match([Tokens.LPAREN, Tokens.LBRACE, Tokens.LBRACKET])){ - - token = tokenStream.token(); - endChar = token.endChar; - value = token.value + this._expr(inFunction).text; - if (unary === null){ - line = tokenStream.token().startLine; - col = tokenStream.token().startCol; - } - tokenStream.mustMatch(Tokens.type(endChar)); - value += endChar; - this._readWhitespace(); - + //see if there's a simple match } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH, Tokens.ANGLE, Tokens.TIME, Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){ - + value = tokenStream.token().value; if (unary === null){ line = tokenStream.token().startLine; @@ -2912,20 +2857,20 @@ Parser.prototype = function(){ } this._readWhitespace(); } else { - + //see if it's a color token = this._hexcolor(); if (token === null){ - + //if there's no unary, get the start of the next token for line/col info if (unary === null){ line = tokenStream.LT(1).startLine; col = tokenStream.LT(1).startCol; - } - + } + //has to be a function if (value === null){ - + /* * This checks for alpha(opacity=0) style of IE * functions. IE_FUNCTION only presents progid: style. @@ -2941,61 +2886,61 @@ Parser.prototype = function(){ return null; //throw new Error("Expected identifier at line " + tokenStream.token().startLine + ", character " + tokenStream.token().startCol + "."); }*/ - + } else { value = token.value; if (unary === null){ line = token.startLine; col = token.startCol; - } + } } - - } - + + } + return value !== null ? new PropertyValuePart(unary !== null ? unary + value : value, line, col) : null; - + }, - + _function: function(){ - + /* * function * : FUNCTION S* expr ')' S* * ; */ - + var tokenStream = this._tokenStream, functionText = null, expr = null, lt; - + if (tokenStream.match(Tokens.FUNCTION)){ functionText = tokenStream.token().value; this._readWhitespace(); expr = this._expr(true); functionText += expr; - + //START: Horrible hack in case it's an IE filter if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ do { - + if (this._readWhitespace()){ functionText += tokenStream.token().value; } - + //might be second time in the loop if (tokenStream.LA(0) == Tokens.COMMA){ functionText += tokenStream.token().value; } - + tokenStream.match(Tokens.IDENT); functionText += tokenStream.token().value; - + tokenStream.match(Tokens.EQUALS); functionText += tokenStream.token().value; - + //functionText += this._term(); lt = tokenStream.peek(); while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ @@ -3007,49 +2952,49 @@ Parser.prototype = function(){ } //END: Horrible Hack - - tokenStream.match(Tokens.RPAREN); + + tokenStream.match(Tokens.RPAREN); functionText += ")"; this._readWhitespace(); - } - + } + return functionText; - }, - + }, + _ie_function: function(){ - + /* (My own extension) * ie_function * : IE_FUNCTION S* IDENT '=' term [S* ','? IDENT '=' term]+ ')' S* * ; */ - + var tokenStream = this._tokenStream, functionText = null, expr = null, lt; - + //IE function can begin like a regular function, too if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){ functionText = tokenStream.token().value; - + do { - + if (this._readWhitespace()){ functionText += tokenStream.token().value; } - + //might be second time in the loop if (tokenStream.LA(0) == Tokens.COMMA){ functionText += tokenStream.token().value; } - + tokenStream.match(Tokens.IDENT); functionText += tokenStream.token().value; - + tokenStream.match(Tokens.EQUALS); functionText += tokenStream.token().value; - + //functionText += this._term(); lt = tokenStream.peek(); while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ @@ -3057,16 +3002,16 @@ Parser.prototype = function(){ functionText += tokenStream.token().value; lt = tokenStream.peek(); } - } while(tokenStream.match([Tokens.COMMA, Tokens.S])); - - tokenStream.match(Tokens.RPAREN); + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + + tokenStream.match(Tokens.RPAREN); functionText += ")"; this._readWhitespace(); - } - + } + return functionText; - }, - + }, + _hexcolor: function(){ /* * There is a constraint on the color that it must @@ -3077,15 +3022,15 @@ Parser.prototype = function(){ * : HASH S* * ; */ - + var tokenStream = this._tokenStream, token = null, color; - + if(tokenStream.match(Tokens.HASH)){ - + //need to do some validation here - + token = tokenStream.token(); color = token.value; if (!/#[a-f0-9]{3,6}/i.test(color)){ @@ -3093,16 +3038,16 @@ Parser.prototype = function(){ } this._readWhitespace(); } - + return token; }, - + //----------------------------------------------------------------- // Animations methods //----------------------------------------------------------------- - + _keyframes: function(){ - + /* * keyframes: * : KEYFRAMES_SYM S* keyframe_name S* '{' S* keyframe_rule* '}' { @@ -3112,53 +3057,53 @@ Parser.prototype = function(){ token, tt, name, - prefix = ""; - + prefix = ""; + tokenStream.mustMatch(Tokens.KEYFRAMES_SYM); token = tokenStream.token(); if (/^@\-([^\-]+)\-/.test(token.value)) { prefix = RegExp.$1; } - + this._readWhitespace(); name = this._keyframe_name(); - + this._readWhitespace(); tokenStream.mustMatch(Tokens.LBRACE); - + this.fire({ type: "startkeyframes", name: name, prefix: prefix, line: token.startLine, col: token.startCol - }); - + }); + this._readWhitespace(); tt = tokenStream.peek(); - + //check for key while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) { this._keyframe_rule(); this._readWhitespace(); tt = tokenStream.peek(); - } - + } + this.fire({ type: "endkeyframes", name: name, prefix: prefix, line: token.startLine, col: token.startCol - }); - + }); + this._readWhitespace(); - tokenStream.mustMatch(Tokens.RBRACE); - + tokenStream.mustMatch(Tokens.RBRACE); + }, - + _keyframe_name: function(){ - + /* * keyframe_name: * : IDENT @@ -3169,41 +3114,41 @@ Parser.prototype = function(){ token; tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); - return SyntaxUnit.fromToken(tokenStream.token()); + return SyntaxUnit.fromToken(tokenStream.token()); }, - + _keyframe_rule: function(){ - + /* * keyframe_rule: - * : key_list S* + * : key_list S* * '{' S* declaration [ ';' S* declaration ]* '}' S* * ; */ var tokenStream = this._tokenStream, token, keyList = this._key_list(); - + this.fire({ type: "startkeyframerule", keys: keyList, line: keyList[0].line, col: keyList[0].col - }); - - this._readDeclarations(true); - + }); + + this._readDeclarations(true); + this.fire({ type: "endkeyframerule", keys: keyList, line: keyList[0].line, col: keyList[0].col - }); - + }); + }, - + _key_list: function(){ - + /* * key_list: * : key [ S* ',' S* key]* @@ -3213,12 +3158,12 @@ Parser.prototype = function(){ token, key, keyList = []; - + //must be least one key keyList.push(this._key()); - + this._readWhitespace(); - + while(tokenStream.match(Tokens.COMMA)){ this._readWhitespace(); keyList.push(this._key()); @@ -3227,7 +3172,7 @@ Parser.prototype = function(){ return keyList; }, - + _key: function(){ /* * There is a restriction that IDENT can be only "from" or "to". @@ -3237,30 +3182,30 @@ Parser.prototype = function(){ * | IDENT * ; */ - + var tokenStream = this._tokenStream, token; - + if (tokenStream.match(Tokens.PERCENTAGE)){ return SyntaxUnit.fromToken(tokenStream.token()); } else if (tokenStream.match(Tokens.IDENT)){ - token = tokenStream.token(); - + token = tokenStream.token(); + if (/from|to/i.test(token.value)){ return SyntaxUnit.fromToken(token); } - + tokenStream.unget(); } - + //if it gets here, there wasn't a valid token, so time to explode this._unexpectedToken(tokenStream.LT(1)); }, - + //----------------------------------------------------------------- // Helper methods //----------------------------------------------------------------- - + /** * Not part of CSS grammar, but useful for skipping over * combination of white space and HTML-style comments. @@ -3293,25 +3238,25 @@ Parser.prototype = function(){ * or * S* '{' S* [ declaration | margin ]? [ ';' S* [ declaration | margin ]? ]* '}' S* * Note that this is how it is described in CSS3 Paged Media, but is actually incorrect. - * A semicolon is only necessary following a declaration is there's another declaration - * or margin afterwards. + * A semicolon is only necessary following a delcaration is there's another declaration + * or margin afterwards. */ var tokenStream = this._tokenStream, tt; - + this._readWhitespace(); - + if (checkStart){ - tokenStream.mustMatch(Tokens.LBRACE); + tokenStream.mustMatch(Tokens.LBRACE); } - + this._readWhitespace(); try { - + while(true){ - + if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){ //noop } else if (this._declaration()){ @@ -3321,19 +3266,19 @@ Parser.prototype = function(){ } else { break; } - + //if ((!this._margin() && !this._declaration()) || !tokenStream.match(Tokens.SEMICOLON)){ // break; //} this._readWhitespace(); } - + tokenStream.mustMatch(Tokens.RBRACE); this._readWhitespace(); - + } catch (ex) { if (ex instanceof SyntaxError && !this.options.strict){ - + //fire error event this.fire({ type: "error", @@ -3341,27 +3286,27 @@ Parser.prototype = function(){ message: ex.message, line: ex.line, col: ex.col - }); - + }); + //see if there's another declaration tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); if (tt == Tokens.SEMICOLON){ //if there's a semicolon, then there might be another declaration - this._readDeclarations(false, readMargins); + this._readDeclarations(false, readMargins); } else if (tt != Tokens.RBRACE){ //if there's a right brace, the rule is finished so don't do anything //otherwise, rethrow the error because it wasn't handled properly throw ex; - } - + } + } else { //not a syntax error, rethrow it throw ex; } - } - - }, - + } + + }, + /** * In some cases, you can end up with two white space tokens in a * row. Instead of making a change in every function that looks for @@ -3372,17 +3317,17 @@ Parser.prototype = function(){ * @private */ _readWhitespace: function(){ - + var tokenStream = this._tokenStream, ws = ""; - + while(tokenStream.match(Tokens.S)){ ws += tokenStream.token().value; } - + return ws; }, - + /** * Throws an error when an unexpected token is found. @@ -3394,7 +3339,7 @@ Parser.prototype = function(){ _unexpectedToken: function(token){ throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); }, - + /** * Helper method used for parsing subparts of a style sheet. * @return {void} @@ -3404,64 +3349,64 @@ Parser.prototype = function(){ _verifyEnd: function(){ if (this._tokenStream.LA(1) != Tokens.EOF){ this._unexpectedToken(this._tokenStream.LT(1)); - } + } }, - + //----------------------------------------------------------------- // Validation methods //----------------------------------------------------------------- _validateProperty: function(property, value){ Validation.validate(property, value); }, - + //----------------------------------------------------------------- // Parsing methods //----------------------------------------------------------------- - - parse: function(input){ + + parse: function(input){ this._tokenStream = new TokenStream(input, Tokens); this._stylesheet(); }, - + parseStyleSheet: function(input){ //just passthrough return this.parse(input); }, - + parseMediaQuery: function(input){ this._tokenStream = new TokenStream(input, Tokens); var result = this._media_query(); - + //if there's anything more, then it's an invalid selector this._verifyEnd(); - + //otherwise return result - return result; + return result; }, - + /** * Parses a property value (everything after the semicolon). * @return {parserlib.css.PropertyValue} The property value. * @throws parserlib.util.SyntaxError If an unexpected token is found. * @method parserPropertyValue - */ + */ parsePropertyValue: function(input){ - + this._tokenStream = new TokenStream(input, Tokens); this._readWhitespace(); - + var result = this._expr(); - + //okay to have a trailing white space this._readWhitespace(); - + //if there's anything more, then it's an invalid selector this._verifyEnd(); - + //otherwise return result return result; }, - + /** * Parses a complete CSS rule, including selectors and * properties. @@ -3471,22 +3416,22 @@ Parser.prototype = function(){ */ parseRule: function(input){ this._tokenStream = new TokenStream(input, Tokens); - + //skip any leading white space this._readWhitespace(); - + var result = this._ruleset(); - + //skip any trailing white space this._readWhitespace(); //if there's anything more, then it's an invalid selector this._verifyEnd(); - + //otherwise return result - return result; + return result; }, - + /** * Parses a single CSS selector (no comma) * @param {String} input The text to parse as a CSS selector. @@ -3495,29 +3440,29 @@ Parser.prototype = function(){ * @method parseSelector */ parseSelector: function(input){ - + this._tokenStream = new TokenStream(input, Tokens); - + //skip any leading white space this._readWhitespace(); - + var result = this._selector(); - + //skip any trailing white space this._readWhitespace(); //if there's anything more, then it's an invalid selector this._verifyEnd(); - + //otherwise return result return result; }, /** - * Parses an HTML style attribute: a set of CSS declarations + * Parses an HTML style attribute: a set of CSS declarations * separated by semicolons. * @param {String} input The text to parse as a style attribute - * @return {void} + * @return {void} * @method parseStyleAttribute */ parseStyleAttribute: function(input){ @@ -3526,14 +3471,14 @@ Parser.prototype = function(){ this._readDeclarations(); } }; - + //copy over onto prototype for (prop in additions){ if (additions.hasOwnProperty(prop)){ proto[prop] = additions[prop]; } - } - + } + return proto; }(); @@ -3548,24 +3493,17 @@ nth var Properties = { //A - "align-items" : "flex-start | flex-end | center | baseline | stretch", - "align-content" : "flex-start | flex-end | center | space-between | space-around | stretch", - "align-self" : "auto | flex-start | flex-end | center | baseline | stretch", - "-webkit-align-items" : "flex-start | flex-end | center | baseline | stretch", - "-webkit-align-content" : "flex-start | flex-end | center | space-between | space-around | stretch", - "-webkit-align-self" : "auto | flex-start | flex-end | center | baseline | stretch", "alignment-adjust" : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ", "alignment-baseline" : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical", "animation" : 1, "animation-delay" : { multi: "
  • ', - '

    juhu', - '

    ', - 'kinners', - '

  • ' - ]); - - var mode = new HtmlMode(); - session.setMode(mode); - session.setFoldStyle("markbeginend"); - - assert.equal(session.getFoldWidget(0), "start"); - assert.equal(session.getFoldWidget(1), "start"); - assert.equal(session.getFoldWidget(2), "start"); - assert.equal(session.getFoldWidget(3), "start"); - assert.equal(session.getFoldWidget(4), ""); - assert.equal(session.getFoldWidget(5), "end"); - - assert.range(session.getFoldWidgetRange(1), 1, 4, 5, 0); } }; diff --git a/lib/ace/mode/folding/ini.js b/lib/ace/mode/folding/ini.js deleted file mode 100644 index ef4eaa0b..00000000 --- a/lib/ace/mode/folding/ini.js +++ /dev/null @@ -1,80 +0,0 @@ -/* ***** 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("./fold_mode").FoldMode; - -var FoldMode = exports.FoldMode = function() { -}; -oop.inherits(FoldMode, BaseFoldMode); - -(function() { - - this.foldingStartMarker = /^\s*\[([^\])]*)]\s*(?:$|[;#])/; - - this.getFoldWidgetRange = function(session, foldStyle, row) { - var re = this.foldingStartMarker; - var line = session.getLine(row); - - var m = line.match(re); - - if (!m) return; - - var startName = m[1] + "."; - - var startColumn = line.length; - var maxRow = session.getLength(); - var startRow = row; - var endRow = row; - - while (++row < maxRow) { - line = session.getLine(row); - if (/^\s*$/.test(line)) - continue; - m = line.match(re); - if (m && m[1].lastIndexOf(startName, 0) !== 0) - break; - - endRow = row; - } - - if (endRow > startRow) { - var endColumn = session.getLine(endRow).length; - return new Range(startRow, startColumn, endRow, endColumn); - } - }; - -}).call(FoldMode.prototype); - -}); diff --git a/lib/ace/mode/folding/latex.js b/lib/ace/mode/folding/latex.js index 6f20b22e..b80775eb 100644 --- a/lib/ace/mode/folding/latex.js +++ b/lib/ace/mode/folding/latex.js @@ -42,7 +42,7 @@ oop.inherits(FoldMode, BaseFoldMode); (function() { - this.foldingStartMarker = /^\s*\\(begin)|(section|subsection|paragraph)\b|{\s*$/; + this.foldingStartMarker = /^\s*\\(begin)|(section|subsection)\b|{\s*$/; this.foldingStopMarker = /^\s*\\(end)\b|^\s*}/; this.getFoldWidgetRange = function(session, foldStyle, row) { @@ -74,7 +74,7 @@ oop.inherits(FoldMode, BaseFoldMode); var stream = new TokenIterator(session, row, column); var token = stream.getCurrentToken(); - if (!token || !(token.type == "storage.type" || token.type == "constant.character.escape")) + if (!token || token.type !== "keyword") return; var val = token.value; @@ -96,7 +96,7 @@ oop.inherits(FoldMode, BaseFoldMode); stream.step = dir === -1 ? stream.stepBackward : stream.stepForward; while(token = stream.step()) { - if (!token || !(token.type == "storage.type" || token.type == "constant.character.escape")) + if (token.type !== "keyword") continue; var level = keywords[token.value]; if (!level) @@ -119,11 +119,11 @@ oop.inherits(FoldMode, BaseFoldMode); }; this.latexSection = function(session, row, column) { - var keywords = ["\\subsection", "\\section", "\\begin", "\\end", "\\paragraph"]; + var keywords = ["\\subsection", "\\section", "\\begin", "\\end"]; var stream = new TokenIterator(session, row, column); var token = stream.getCurrentToken(); - if (!token || token.type != "storage.type") + if (!token || token.type != "keyword") return; var startLevel = keywords.indexOf(token.value); @@ -131,7 +131,7 @@ oop.inherits(FoldMode, BaseFoldMode); var endRow = row; while(token = stream.stepForward()) { - if (token.type !== "storage.type") + if (token.type !== "keyword") continue; var level = keywords.indexOf(token.value); diff --git a/lib/ace/mode/folding/mixed.js b/lib/ace/mode/folding/mixed.js index 40d2cda8..3dd48a7d 100644 --- a/lib/ace/mode/folding/mixed.js +++ b/lib/ace/mode/folding/mixed.js @@ -59,6 +59,8 @@ oop.inherits(FoldMode, BaseFoldMode); }; this.getFoldWidget = function(session, foldStyle, row) { + if (session.bgTokenizer.currentLine < row) + return; return ( this.$tryMode(session.getState(row-1), session, foldStyle, row) || this.$tryMode(session.getState(row), session, foldStyle, row) || diff --git a/lib/ace/mode/folding/sqlserver.js b/lib/ace/mode/folding/sqlserver.js deleted file mode 100644 index b3fd4e93..00000000 --- a/lib/ace/mode/folding/sqlserver.js +++ /dev/null @@ -1,111 +0,0 @@ -/* ***** 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); - -}); diff --git a/lib/ace/mode/folding/xml.js b/lib/ace/mode/folding/xml.js index 7565bf15..7c0d949c 100644 --- a/lib/ace/mode/folding/xml.js +++ b/lib/ace/mode/folding/xml.js @@ -3,7 +3,7 @@ * * 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 @@ -14,7 +14,7 @@ * * 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 @@ -37,101 +37,62 @@ var Range = require("../../range").Range; var BaseFoldMode = require("./fold_mode").FoldMode; var TokenIterator = require("../../token_iterator").TokenIterator; -var FoldMode = exports.FoldMode = function(voidElements, optionalEndTags) { +var FoldMode = exports.FoldMode = function(voidElements) { BaseFoldMode.call(this); this.voidElements = voidElements || {}; - this.optionalEndTags = oop.mixin({}, this.voidElements); - if (optionalEndTags) - oop.mixin(this.optionalEndTags, optionalEndTags); - }; oop.inherits(FoldMode, BaseFoldMode); -var Tag = function() { - this.tagName = ""; - this.closing = false; - this.selfClosing = false; - this.start = {row: 0, column: 0}; - this.end = {row: 0, column: 0}; -}; - -function is(token, type) { - return token.type.lastIndexOf(type + ".xml") > -1; -} - (function() { this.getFoldWidget = function(session, foldStyle, row) { var tag = this._getFirstTagInLine(session, row); - if (!tag) - return ""; - - if (tag.closing || (!tag.tagName && tag.selfClosing)) + if (tag.closing) return foldStyle == "markbeginend" ? "end" : ""; - if (!tag.tagName || tag.selfClosing || this.voidElements.hasOwnProperty(tag.tagName.toLowerCase())) + if (!tag.tagName || this.voidElements[tag.tagName.toLowerCase()]) return ""; - if (this._findEndTagInLine(session, row, tag.tagName, tag.end.column)) + if (tag.selfClosing) + return ""; + + if (tag.value.indexOf("/" + tag.tagName) !== -1) return ""; return "start"; }; - - /* - * returns a first tag (or a fragment) in a line - */ + this._getFirstTagInLine = function(session, row) { var tokens = session.getTokens(row); - var tag = new Tag(); - + var value = ""; for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; - if (is(token, "tag-open")) { - tag.end.column = tag.start.column + token.value.length; - tag.closing = is(token, "end-tag-open"); - token = tokens[++i]; - if (!token) - return null; - tag.tagName = token.value; - tag.end.column += token.value.length; - for (i++; i < tokens.length; i++) { - token = tokens[i]; - tag.end.column += token.value.length; - if (is(token, "tag-close")) { - tag.selfClosing = token.value == '/>'; - break; - } - } - return tag; - } else if (is(token, "tag-close")) { - tag.selfClosing = token.value == '/>'; - return tag; - } - tag.start.column += token.value.length; + if (token.type.lastIndexOf("meta.tag", 0) === 0) + value += token.value; + else + value += lang.stringRepeat(" ", token.value.length); } - - return null; + + return this._parseTag(value); }; - this._findEndTagInLine = function(session, row, tagName, startColumn) { - var tokens = session.getTokens(row); + this.tagRe = /^(\s*)(?)/; + this._parseTag = function(tag) { + + var match = tag.match(this.tagRe); var column = 0; - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - column += token.value.length; - if (column < startColumn) - continue; - if (is(token, "end-tag-open")) { - token = tokens[i + 1]; - if (token && token.value == tagName) - return true; - } - } - return false; - }; + return { + value: tag, + match: match ? match[2] : "", + closing: match ? !!match[3] : false, + selfClosing: match ? !!match[5] || match[2] == "/>" : false, + tagName: match ? match[4] : "", + column: match[1] ? column + match[1].length : column + }; + }; + /* * reads a full tag and places the iterator after the tag */ @@ -139,24 +100,32 @@ function is(token, type) { var token = iterator.getCurrentToken(); if (!token) return null; - - var tag = new Tag(); + + var value = ""; + var start; + do { - if (is(token, "tag-open")) { - tag.closing = is(token, "end-tag-open"); - tag.start.row = iterator.getCurrentTokenRow(); - tag.start.column = iterator.getCurrentTokenColumn(); - } else if (is(token, "tag-name")) { - tag.tagName = token.value; - } else if (is(token, "tag-close")) { - tag.selfClosing = token.value == "/>"; - tag.end.row = iterator.getCurrentTokenRow(); - tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; - iterator.stepForward(); - return tag; + if (token.type.lastIndexOf("meta.tag", 0) === 0) { + if (!start) { + var start = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + }; + } + value += token.value; + if (token.type.slice(-4) === ".end") { + var tag = this._parseTag(value); + tag.start = start; + tag.end = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + token.value.length + }; + iterator.stepForward(); + return tag; + } } } while(token = iterator.stepForward()); - + return null; }; @@ -164,35 +133,45 @@ function is(token, type) { var token = iterator.getCurrentToken(); if (!token) return null; + + var value = ""; + var end; - var tag = new Tag(); do { - if (is(token, "tag-open")) { - tag.closing = is(token, "end-tag-open"); - tag.start.row = iterator.getCurrentTokenRow(); - tag.start.column = iterator.getCurrentTokenColumn(); - iterator.stepBackward(); - return tag; - } else if (is(token, "tag-name")) { - tag.tagName = token.value; - } else if (is(token, "tag-close")) { - tag.selfClosing = token.value == "/>"; - tag.end.row = iterator.getCurrentTokenRow(); - tag.end.column = iterator.getCurrentTokenColumn() + token.value.length; + if (token.type.lastIndexOf("meta.tag", 0) === 0) { + if (!end) { + end = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + token.value.length + }; + } + value = token.value + value; + if (value.indexOf("<") !== -1) { + var tag = this._parseTag(value); + tag.end = end; + tag.start = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + }; + iterator.stepBackward(); + return tag; + } } } while(token = iterator.stepBackward()); - + return null; }; this._pop = function(stack, tag) { while (stack.length) { - var top = stack[stack.length-1]; if (!tag || top.tagName == tag.tagName) { return stack.pop(); } - else if (this.optionalEndTags.hasOwnProperty(top.tagName)) { + else if (this.voidElements[tag.tagName]) { + return; + } + else if (this.voidElements[top.tagName]) { stack.pop(); continue; } else { @@ -204,7 +183,7 @@ function is(token, type) { this.getFoldWidgetRange = function(session, foldStyle, row) { var firstTag = this._getFirstTagInLine(session, row); - if (!firstTag) + if (!firstTag.match) return null; var isBackward = firstTag.closing || firstTag.selfClosing; @@ -212,13 +191,11 @@ function is(token, type) { var tag; if (!isBackward) { - var iterator = new TokenIterator(session, row, firstTag.start.column); + var iterator = new TokenIterator(session, row, firstTag.column); var start = { row: row, - column: firstTag.start.column + firstTag.tagName.length + 2 + column: firstTag.column + firstTag.match.length }; - if (firstTag.start.row == firstTag.end.row) - start.column = firstTag.end.column; while (tag = this._readTagForward(iterator)) { if (tag.selfClosing) { if (!stack.length) { @@ -231,19 +208,20 @@ function is(token, type) { if (tag.closing) { this._pop(stack, tag); - if (stack.length == 0) + if (!stack.length) return Range.fromPoints(start, tag.start); + } else { - stack.push(tag); + stack.push(tag) } } } else { - var iterator = new TokenIterator(session, row, firstTag.end.column); + var iterator = new TokenIterator(session, row, firstTag.column + firstTag.match.length); var end = { row: row, - column: firstTag.start.column + column: firstTag.column }; while (tag = this._readTagBackward(iterator)) { @@ -258,21 +236,94 @@ function is(token, type) { if (!tag.closing) { this._pop(stack, tag); - if (stack.length == 0) { - tag.start.column += tag.tagName.length + 2; - if (tag.start.row == tag.end.row && tag.start.column < tag.end.column) - tag.start.column = tag.end.column; - return Range.fromPoints(tag.start, end); + if (!stack.length) { + if (tag.start.row != tag.end.row) { + tag.end = tag.start; + tag.end.column += session.getLine(tag.end.row).length; + } + return Range.fromPoints(tag.end, end); } } else { - stack.push(tag); + stack.push(tag) } } } - + }; + this.getMatching = function(session, row, column) { + if (row == undefined) + row = session.selection.lead + if (typeof row == "object") { + column = row.column; + row = row.row; + } + + var TAG_NAME = "meta.tag.name"; + + var iterator = new TokenIterator(session, row, column); + var startToken = iterator.getCurrentToken(); + if (!startToken) + return; + if (startToken.type.lastIndexOf(TAG_NAME, 0) == 0) { + startToken = iterator.stepBackward(); + } else + return; + + var isBackward = startToken.value == "" - }, { - token : "comment", - regex : "\\|(?=.)", - next : "table-item" - }, { - token : "comment", - regex : "\\|$", - next : "start" - }], - "qqstring3" : [ { - token : "constant.language.escape", - regex : stringEscape - }, { - token : "string", // multi line """ string end - regex : '"{3}', - next : "start" - }, { - defaultToken : "string" - }], - "qqstring" : [{ - token : "constant.language.escape", - regex : stringEscape - }, { - token : "string", - regex : "\\\\$", - next : "qqstring" - }, { - token : "string", - regex : '"|$', - next : "start" - }, { - defaultToken: "string" - }], - "table-item" : [{ - token : "comment", - regex : /$/, - next : "start" - }, { - token : "comment", - regex : /\|/ - }, { - token : "string", - regex : /\\./ - }, { - defaultToken : "string" - }] - }; -} - -oop.inherits(GherkinHighlightRules, TextHighlightRules); - -exports.GherkinHighlightRules = GherkinHighlightRules; -}); \ No newline at end of file diff --git a/lib/ace/mode/gitignore.js b/lib/ace/mode/gitignore.js deleted file mode 100644 index fa263985..00000000 --- a/lib/ace/mode/gitignore.js +++ /dev/null @@ -1,20 +0,0 @@ - -define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var TextMode = require("./text").Mode; -var GitignoreHighlightRules = require("./gitignore_highlight_rules").GitignoreHighlightRules; - -var Mode = function() { - this.HighlightRules = GitignoreHighlightRules; -}; -oop.inherits(Mode, TextMode); - -(function() { - this.lineCommentStart = "#"; - this.$id = "ace/mode/gitignore"; -}).call(Mode.prototype); - -exports.Mode = Mode; -}); diff --git a/lib/ace/mode/gitignore_highlight_rules.js b/lib/ace/mode/gitignore_highlight_rules.js deleted file mode 100644 index cfa42afa..00000000 --- a/lib/ace/mode/gitignore_highlight_rules.js +++ /dev/null @@ -1,31 +0,0 @@ -define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; - -var GitignoreHighlightRules = function() { - this.$rules = { - "start" : [ - { - token : "comment", - regex : /^\s*#.*$/ - }, { - token : "keyword", // negated patterns - regex : /^\s*!.*$/ - } - ] - }; - - this.normalizeRules(); -}; - -GitignoreHighlightRules.metaData = { - fileTypes: ['gitignore'], - name: 'Gitignore' -}; - -oop.inherits(GitignoreHighlightRules, TextHighlightRules); - -exports.GitignoreHighlightRules = GitignoreHighlightRules; -}); diff --git a/lib/ace/mode/glsl.js b/lib/ace/mode/glsl.js index dab63106..ef2a2b44 100644 --- a/lib/ace/mode/glsl.js +++ b/lib/ace/mode/glsl.js @@ -33,6 +33,7 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var CMode = require("./c_cpp").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var glslHighlightRules = require("./glsl_highlight_rules").glslHighlightRules; var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var Range = require("../range").Range; @@ -40,17 +41,15 @@ var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = glslHighlightRules; + var highlighter = new glslHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); + this.$keywordList = highlighter.$keywordList; this.foldingRules = new CStyleFoldMode(); }; oop.inherits(Mode, CMode); -(function() { - this.$id = "ace/mode/glsl"; -}).call(Mode.prototype); - exports.Mode = Mode; }); diff --git a/lib/ace/mode/golang.js b/lib/ace/mode/golang.js index a13fbb24..91b3e085 100644 --- a/lib/ace/mode/golang.js +++ b/lib/ace/mode/golang.js @@ -2,13 +2,17 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var GolangHighlightRules = require("./golang_highlight_rules").GolangHighlightRules; var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = GolangHighlightRules; + var highlighter = new GolangHighlightRules(); + + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$keywordList = highlighter.$keywordList; this.$outdent = new MatchingBraceOutdent(); this.foldingRules = new CStyleFoldMode(); }; @@ -22,7 +26,7 @@ oop.inherits(Mode, TextMode); this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); - var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); var tokens = tokenizedLine.tokens; var endState = tokenizedLine.state; @@ -48,7 +52,6 @@ oop.inherits(Mode, TextMode); this.$outdent.autoOutdent(doc, row); }; - this.$id = "ace/mode/golang"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/golang_highlight_rules.js b/lib/ace/mode/golang_highlight_rules.js index 2369c8cb..5bd40b44 100644 --- a/lib/ace/mode/golang_highlight_rules.js +++ b/lib/ace/mode/golang_highlight_rules.js @@ -72,6 +72,9 @@ define(function(require, exports, module) { }, { token : "paren.rparen", regex : "[\\])}]" + }, { + token: "invalid", + regex: "\\s+$" }, { token : "text", regex : "\\s+" diff --git a/lib/ace/mode/groovy.js b/lib/ace/mode/groovy.js index 107998bf..65d87cd4 100644 --- a/lib/ace/mode/groovy.js +++ b/lib/ace/mode/groovy.js @@ -3,11 +3,14 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var JavaScriptMode = require("./javascript").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var GroovyHighlightRules = require("./groovy_highlight_rules").GroovyHighlightRules; var Mode = function() { JavaScriptMode.call(this); - this.HighlightRules = GroovyHighlightRules; + var highlighter = new GroovyHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$keywordList = highlighter.$keywordList; }; oop.inherits(Mode, JavaScriptMode); @@ -17,7 +20,6 @@ oop.inherits(Mode, JavaScriptMode); return null; }; - this.$id = "ace/mode/groovy"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/haml.js b/lib/ace/mode/haml.js index f6a59e23..7970aff2 100644 --- a/lib/ace/mode/haml.js +++ b/lib/ace/mode/haml.js @@ -42,19 +42,21 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var HamlHighlightRules = require("./haml_highlight_rules").HamlHighlightRules; var FoldMode = require("./folding/coffee").FoldMode; var Mode = function() { - this.HighlightRules = HamlHighlightRules; - this.foldingRules = new FoldMode(); + var highlighter = new HamlHighlightRules(); + this.foldingRules = new FoldMode(); + + this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = ["//", "#"]; - this.$id = "ace/mode/haml"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/handlebars.js b/lib/ace/mode/handlebars.js deleted file mode 100644 index 164ad43f..00000000 --- a/lib/ace/mode/handlebars.js +++ /dev/null @@ -1,28 +0,0 @@ -/* global define */ - -define(function(require, exports, module) { - "use strict"; - -var oop = require("../lib/oop"); -var HtmlMode = require("./html").Mode; -var HandlebarsHighlightRules = require("./handlebars_highlight_rules").HandlebarsHighlightRules; -var HtmlBehaviour = require("./behaviour/html").HtmlBehaviour; -var HtmlFoldMode = require("./folding/html").FoldMode; - -var Mode = function() { - HtmlMode.call(this); - this.HighlightRules = HandlebarsHighlightRules; - this.$behaviour = new HtmlBehaviour(); - - this.foldingRules = new HtmlFoldMode(); -}; - -oop.inherits(Mode, HtmlMode); - -(function() { - this.blockComment = {start: "{{!--", end: "--}}"}; - this.$id = "ace/mode/handlebars"; -}).call(Mode.prototype); - -exports.Mode = Mode; -}); diff --git a/lib/ace/mode/handlebars_highlight_rules.js b/lib/ace/mode/handlebars_highlight_rules.js deleted file mode 100644 index f91a48ec..00000000 --- a/lib/ace/mode/handlebars_highlight_rules.js +++ /dev/null @@ -1,72 +0,0 @@ -/* global define */ - -define(function(require, exports, module) { -"use strict"; - -var oop = require("../lib/oop"); -var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules; - -function pop2(currentState, stack) { - stack.splice(0, 3); - return stack.shift() || "start"; -} -var HandlebarsHighlightRules = function() { - HtmlHighlightRules.call(this); - var hbs = { - regex : "(?={{)", - push : "handlebars" - }; - for (var key in this.$rules) { - this.$rules[key].unshift(hbs); - } - this.$rules.handlebars = [{ - token : "comment.start", - regex : "{{!--", - push : [{ - token : "comment.end", - regex : "--}}", - next : pop2 - }, { - defaultToken : "comment" - }] - }, { - token : "comment.start", - regex : "{{!", - push : [{ - token : "comment.end", - regex : "}}", - next : pop2 - }, { - defaultToken : "comment" - }] - }, { - token : "support.function", // unescaped variable - regex : "{{{", - push : [{ - token : "support.function", - regex : "}}}", - next : pop2 - }, { - token : "variable.parameter", - regex : "[a-zA-Z_$][a-zA-Z0-9_$]*" - }] - }, { - token : "storage.type.start", // begin section - regex : "{{[#\\^/&]?", - push : [{ - token : "storage.type.end", - regex : "}}", - next : pop2 - }, { - token : "variable.parameter", - regex : "[a-zA-Z_$][a-zA-Z0-9_$]*" - }] - }]; - - this.normalizeRules(); -}; - -oop.inherits(HandlebarsHighlightRules, HtmlHighlightRules); - -exports.HandlebarsHighlightRules = HandlebarsHighlightRules; -}); diff --git a/lib/ace/mode/haskell.js b/lib/ace/mode/haskell.js index 05cc94a0..11e6c17d 100644 --- a/lib/ace/mode/haskell.js +++ b/lib/ace/mode/haskell.js @@ -42,20 +42,22 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var HaskellHighlightRules = require("./haskell_highlight_rules").HaskellHighlightRules; // TODO: pick appropriate fold mode var FoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = HaskellHighlightRules; + var highlighter = new HaskellHighlightRules(); this.foldingRules = new FoldMode(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = "--"; this.blockComment = {start: "/*", end: "*/"}; - this.$id = "ace/mode/haskell"; + // Extra logic goes here. }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/haskell_highlight_rules.js b/lib/ace/mode/haskell_highlight_rules.js index 04343ae9..fdfaa53e 100644 --- a/lib/ace/mode/haskell_highlight_rules.js +++ b/lib/ace/mode/haskell_highlight_rules.js @@ -55,9 +55,9 @@ var HaskellHighlightRules = function() { { token: 'constant.language.empty-list.haskell', regex: '\\[\\]' }, { token: 'keyword.other.haskell', - regex: '\\bmodule\\b', + regex: 'module', push: - [ { token: 'keyword.other.haskell', regex: '\\bwhere\\b', next: 'pop' }, + [ { token: 'keyword.other.haskell', regex: 'where', next: 'pop' }, { include: '#module_name' }, { include: '#module_exports' }, { token: 'invalid', regex: '[a-z]+' }, diff --git a/lib/ace/mode/haxe.js b/lib/ace/mode/haxe.js index e2ac5a26..3933a769 100644 --- a/lib/ace/mode/haxe.js +++ b/lib/ace/mode/haxe.js @@ -3,16 +3,19 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var HaxeHighlightRules = require("./haxe_highlight_rules").HaxeHighlightRules; var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = HaxeHighlightRules; + var highlighter = new HaxeHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); + this.$keywordList = highlighter.$keywordList; this.foldingRules = new CStyleFoldMode(); }; oop.inherits(Mode, TextMode); @@ -24,7 +27,7 @@ oop.inherits(Mode, TextMode); this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); - var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); var tokens = tokenizedLine.tokens; if (tokens.length && tokens[tokens.length-1].type == "comment") { @@ -49,7 +52,6 @@ oop.inherits(Mode, TextMode); this.$outdent.autoOutdent(doc, row); }; - this.$id = "ace/mode/haxe"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/html.js b/lib/ace/mode/html.js index a74ee3de..b56ec4b0 100644 --- a/lib/ace/mode/html.js +++ b/lib/ace/mode/html.js @@ -32,32 +32,28 @@ define(function(require, exports, module) { "use strict"; var oop = require("../lib/oop"); -var lang = require("../lib/lang"); var TextMode = require("./text").Mode; var JavaScriptMode = require("./javascript").Mode; var CssMode = require("./css").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules; -var XmlBehaviour = require("./behaviour/xml").XmlBehaviour; +var HtmlBehaviour = require("./behaviour/html").HtmlBehaviour; var HtmlFoldMode = require("./folding/html").FoldMode; var HtmlCompletions = require("./html_completions").HtmlCompletions; -var WorkerClient = require("../worker/worker_client").WorkerClient; -// http://www.w3.org/TR/html5/syntax.html#void-elements -var voidElements = ["area", "base", "br", "col", "embed", "hr", "img", "input", "keygen", "link", "meta", "menuitem", "param", "source", "track", "wbr"]; -var optionalEndTags = ["li", "dt", "dd", "p", "rt", "rp", "optgroup", "option", "colgroup", "td", "th"]; - -var Mode = function(options) { - this.fragmentContext = options && options.fragmentContext; - this.HighlightRules = HtmlHighlightRules; - this.$behaviour = new XmlBehaviour(); +var Mode = function() { + var highlighter = new HtmlHighlightRules(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$behaviour = new HtmlBehaviour(); this.$completer = new HtmlCompletions(); + this.$embeds = highlighter.getEmbeds(); this.createModeDelegates({ "js-": JavaScriptMode, "css-": CssMode }); - this.foldingRules = new HtmlFoldMode(this.voidElements, lang.arrayToMap(optionalEndTags)); + this.foldingRules = new HtmlFoldMode(); }; oop.inherits(Mode, TextMode); @@ -65,8 +61,6 @@ oop.inherits(Mode, TextMode); this.blockComment = {start: ""}; - this.voidElements = lang.arrayToMap(voidElements); - this.getNextLineIndent = function(state, line, tab) { return this.$getIndent(line); }; @@ -75,31 +69,14 @@ oop.inherits(Mode, TextMode); return false; }; + this.getMatching = function(session, row, column) { + return this.foldingRules.defaultMode.getMatching(session, row, column); + }; + this.getCompletions = function(state, session, pos, prefix) { return this.$completer.getCompletions(state, session, pos, prefix); }; - this.createWorker = function(session) { - if (this.constructor != Mode) - return; - var worker = new WorkerClient(["ace"], "ace/mode/html_worker", "Worker"); - worker.attachToDocument(session.getDocument()); - - if (this.fragmentContext) - worker.call("setOptions", [{context: this.fragmentContext}]); - - worker.on("error", function(e) { - session.setAnnotations(e.data); - }); - - worker.on("terminate", function() { - session.clearAnnotations(); - }); - - return worker; - }; - - this.$id = "ace/mode/html"; }).call(Mode.prototype); exports.Mode = Mode; diff --git a/lib/ace/mode/html/saxparser.js b/lib/ace/mode/html/saxparser.js deleted file mode 100644 index e19e1fc4..00000000 --- a/lib/ace/mode/html/saxparser.js +++ /dev/null @@ -1,10430 +0,0 @@ -define(function(require, exports, module) { -module.exports = (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0; i--) { - var node = this.elements[i]; - if (node.localName === localName) - return true; - if (isMarker(node)) - return false; - } -}; - -/** - * Pushes the item on the stack top - * @param {StackItem} item - */ -ElementStack.prototype.push = function(item) { - this.elements.push(item); -}; - -/** - * Pushes the item on the stack top - * @param {StackItem} item HTML element stack item - */ -ElementStack.prototype.pushHtmlElement = function(item) { - this.rootNode = item.node; - this.push(item); -}; - -/** - * Pushes the item on the stack top - * @param {StackItem} item HEAD element stack item - */ -ElementStack.prototype.pushHeadElement = function(item) { - this.headElement = item.node; - this.push(item); -}; - -/** - * Pushes the item on the stack top - * @param {StackItem} item BODY element stack item - */ -ElementStack.prototype.pushBodyElement = function(item) { - this.bodyElement = item.node; - this.push(item); -}; - -/** - * Pops the topmost item - * @return {StackItem} - */ -ElementStack.prototype.pop = function() { - return this.elements.pop(); -}; - -/** - * Removes the item from the element stack - * @param {StackItem} item The item to remove - */ -ElementStack.prototype.remove = function(item) { - this.elements.splice(this.elements.indexOf(item), 1); -}; - -/** - * Pops until an element with a given localName is popped - * @param {String} localName - */ -ElementStack.prototype.popUntilPopped = function(localName) { - var element; - do { - element = this.pop(); - } while (element.localName != localName); -}; - -ElementStack.prototype.popUntilTableScopeMarker = function() { - while (!isTableScopeMarker(this.top)) - this.pop(); -}; - -ElementStack.prototype.popUntilTableBodyScopeMarker = function() { - while (!isTableBodyScopeMarker(this.top)) - this.pop(); -}; - -ElementStack.prototype.popUntilTableRowScopeMarker = function() { - while (!isTableRowScopeMarker(this.top)) - this.pop(); -}; - -/** - * - * @param {Number} index - * @return {StackItem} - */ -ElementStack.prototype.item = function(index) { - return this.elements[index]; -}; - -/** - * - * @param {StackItem} element - * @return {Boolean} - */ -ElementStack.prototype.contains = function(element) { - return this.elements.indexOf(element) !== -1; -}; - -/** - * - * @param {String} localName - * @return {Boolean} - */ -ElementStack.prototype.inScope = function(localName) { - return this._inScope(localName, isScopeMarker); -}; - -/** - * - * @param {String} localName - * @return {Boolean} - */ -ElementStack.prototype.inListItemScope = function(localName) { - return this._inScope(localName, isListItemScopeMarker); -}; - -/** - * - * @param {String} localName - * @return {Boolean} - */ -ElementStack.prototype.inTableScope = function(localName) { - return this._inScope(localName, isTableScopeMarker); -}; - -/** - * - * @param {String} localName - * @return {Boolean} - */ -ElementStack.prototype.inButtonScope = function(localName) { - return this._inScope(localName, isButtonScopeMarker); -}; - -/** - * - * @param {String} localName - * @return {Boolean} - */ -ElementStack.prototype.inSelectScope = function(localName) { - return this._inScope(localName, isSelectScopeMarker); -}; - -/** - * - * @return {Boolean} - */ -ElementStack.prototype.hasNumberedHeaderElementInScope = function() { - for (var i = this.elements.length - 1; i >= 0; i--) { - var node = this.elements[i]; - if (node.isNumberedHeader()) - return true; - if (isScopeMarker(node)) - return false; - } -}; - -/** - * - * @param {Object} element - * @return {StackItem} - */ -ElementStack.prototype.furthestBlockForFormattingElement = function(element) { - var furthestBlock = null; - for (var i = this.elements.length - 1; i >= 0; i--) { - var node = this.elements[i]; - if (node.node === element) - break; - if (node.isSpecial()) - furthestBlock = node; - } - return furthestBlock; -}; - -/** - * - * @param {String} localName - * @return {Number} - */ -ElementStack.prototype.findIndex = function(localName) { - for (var i = this.elements.length - 1; i >= 0; i--) { - if (this.elements[i].localName == localName) - return i; - } - return -1; -}; - -ElementStack.prototype.remove_openElements_until = function(callback) { - var finished = false; - var element; - while (!finished) { - element = this.elements.pop(); - finished = callback(element); - } - return element; -}; - -Object.defineProperty(ElementStack.prototype, 'top', { - get: function() { - return this.elements[this.elements.length - 1]; - } -}); - -Object.defineProperty(ElementStack.prototype, 'length', { - get: function() { - return this.elements.length; - } -}); - -exports.ElementStack = ElementStack; - -}, -{}], -2:[function(_dereq_,module,exports){ -var entities = _dereq_('html5-entities'); -var InputStream = _dereq_('./InputStream').InputStream; - -var namedEntityPrefixes = {}; -Object.keys(entities).forEach(function (entityKey) { - for (var i = 0; i < entityKey.length; i++) { - namedEntityPrefixes[entityKey.substring(0, i + 1)] = true; - } -}); - -function isAlphaNumeric(c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); -} - -function isHexDigit(c) { - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - -function isDecimalDigit(c) { - return (c >= '0' && c <= '9'); -} - -var EntityParser = {}; - -EntityParser.consumeEntity = function(buffer, tokenizer, additionalAllowedCharacter) { - var decodedCharacter = ''; - var consumedCharacters = ''; - var ch = buffer.char(); - if (ch === InputStream.EOF) - return false; - consumedCharacters += ch; - if (ch == '\t' || ch == '\n' || ch == '\v' || ch == ' ' || ch == '<' || ch == '&') { - buffer.unget(consumedCharacters); - return false; - } - if (additionalAllowedCharacter === ch) { - buffer.unget(consumedCharacters); - return false; - } - if (ch == '#') { - ch = buffer.shift(1); - if (ch === InputStream.EOF) { - tokenizer._parseError("expected-numeric-entity-but-got-eof"); - buffer.unget(consumedCharacters); - return false; - } - consumedCharacters += ch; - var radix = 10; - var isDigit = isDecimalDigit; - if (ch == 'x' || ch == 'X') { - radix = 16; - isDigit = isHexDigit; - ch = buffer.shift(1); - if (ch === InputStream.EOF) { - tokenizer._parseError("expected-numeric-entity-but-got-eof"); - buffer.unget(consumedCharacters); - return false; - } - consumedCharacters += ch; - } - if (isDigit(ch)) { - var code = ''; - while (ch !== InputStream.EOF && isDigit(ch)) { - code += ch; - ch = buffer.char(); - } - code = parseInt(code, radix); - var replacement = this.replaceEntityNumbers(code); - if (replacement) { - tokenizer._parseError("invalid-numeric-entity-replaced"); - code = replacement; - } - if (code > 0xFFFF && code <= 0x10FFFF) { - // we substract 0x10000 from cp to get a 20-bits number - // in the range 0..0xFFFF - code -= 0x10000; - // we add 0xD800 to the number formed by the first 10 bits - // to give the first byte - var first = ((0xffc00 & code) >> 10) + 0xD800; - // we add 0xDC00 to the number formed by the low 10 bits - // to give the second byte - var second = (0x3ff & code) + 0xDC00; - decodedCharacter = String.fromCharCode(first, second); - } else - decodedCharacter = String.fromCharCode(code); - if (ch !== ';') { - tokenizer._parseError("numeric-entity-without-semicolon"); - buffer.unget(ch); - } - return decodedCharacter; - } - buffer.unget(consumedCharacters); - tokenizer._parseError("expected-numeric-entity"); - return false; - } - if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { - var mostRecentMatch = ''; - while (namedEntityPrefixes[consumedCharacters]) { - if (entities[consumedCharacters]) { - mostRecentMatch = consumedCharacters; - } - if (ch == ';') - break; - ch = buffer.char(); - if (ch === InputStream.EOF) - break; - consumedCharacters += ch; - } - if (!mostRecentMatch) { - tokenizer._parseError("expected-named-entity"); - buffer.unget(consumedCharacters); - return false; - } - decodedCharacter = entities[mostRecentMatch]; - if (ch === ';' || !additionalAllowedCharacter || !(isAlphaNumeric(ch) || ch === '=')) { - if (consumedCharacters.length > mostRecentMatch.length) { - buffer.unget(consumedCharacters.substring(mostRecentMatch.length)); - } - if (ch !== ';') { - tokenizer._parseError("named-entity-without-semicolon"); - } - return decodedCharacter; - } - buffer.unget(consumedCharacters); - return false; - } -}; - -EntityParser.replaceEntityNumbers = function(c) { - switch(c) { - case 0x00: return 0xFFFD; // REPLACEMENT CHARACTER - case 0x13: return 0x0010; // Carriage return - case 0x80: return 0x20AC; // EURO SIGN - case 0x81: return 0x0081; // - case 0x82: return 0x201A; // SINGLE LOW-9 QUOTATION MARK - case 0x83: return 0x0192; // LATIN SMALL LETTER F WITH HOOK - case 0x84: return 0x201E; // DOUBLE LOW-9 QUOTATION MARK - case 0x85: return 0x2026; // HORIZONTAL ELLIPSIS - case 0x86: return 0x2020; // DAGGER - case 0x87: return 0x2021; // DOUBLE DAGGER - case 0x88: return 0x02C6; // MODIFIER LETTER CIRCUMFLEX ACCENT - case 0x89: return 0x2030; // PER MILLE SIGN - case 0x8A: return 0x0160; // LATIN CAPITAL LETTER S WITH CARON - case 0x8B: return 0x2039; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - case 0x8C: return 0x0152; // LATIN CAPITAL LIGATURE OE - case 0x8D: return 0x008D; // - case 0x8E: return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON - case 0x8F: return 0x008F; // - case 0x90: return 0x0090; // - case 0x91: return 0x2018; // LEFT SINGLE QUOTATION MARK - case 0x92: return 0x2019; // RIGHT SINGLE QUOTATION MARK - case 0x93: return 0x201C; // LEFT DOUBLE QUOTATION MARK - case 0x94: return 0x201D; // RIGHT DOUBLE QUOTATION MARK - case 0x95: return 0x2022; // BULLET - case 0x96: return 0x2013; // EN DASH - case 0x97: return 0x2014; // EM DASH - case 0x98: return 0x02DC; // SMALL TILDE - case 0x99: return 0x2122; // TRADE MARK SIGN - case 0x9A: return 0x0161; // LATIN SMALL LETTER S WITH CARON - case 0x9B: return 0x203A; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - case 0x9C: return 0x0153; // LATIN SMALL LIGATURE OE - case 0x9D: return 0x009D; // - case 0x9E: return 0x017E; // LATIN SMALL LETTER Z WITH CARON - case 0x9F: return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS - default: - if ((c >= 0xD800 && c <= 0xDFFF) || c > 0x10FFFF) { - return 0xFFFD; - } else if ((c >= 0x0001 && c <= 0x0008) || (c >= 0x000E && c <= 0x001F) || - (c >= 0x007F && c <= 0x009F) || (c >= 0xFDD0 && c <= 0xFDEF) || - c == 0x000B || c == 0xFFFE || c == 0x1FFFE || c == 0x2FFFFE || - c == 0x2FFFF || c == 0x3FFFE || c == 0x3FFFF || c == 0x4FFFE || - c == 0x4FFFF || c == 0x5FFFE || c == 0x5FFFF || c == 0x6FFFE || - c == 0x6FFFF || c == 0x7FFFE || c == 0x7FFFF || c == 0x8FFFE || - c == 0x8FFFF || c == 0x9FFFE || c == 0x9FFFF || c == 0xAFFFE || - c == 0xAFFFF || c == 0xBFFFE || c == 0xBFFFF || c == 0xCFFFE || - c == 0xCFFFF || c == 0xDFFFE || c == 0xDFFFF || c == 0xEFFFE || - c == 0xEFFFF || c == 0xFFFFE || c == 0xFFFFF || c == 0x10FFFE || - c == 0x10FFFF) { - return c; - } - } -}; - -exports.EntityParser = EntityParser; - -}, -{"./InputStream":3,"html5-entities":12}], -3:[function(_dereq_,module,exports){ -// FIXME convert CR to LF http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#input-stream -function InputStream() { - this.data = ''; - this.start = 0; - this.committed = 0; - this.eof = false; - this.lastLocation = {line: 0, column: 0}; -} - -InputStream.EOF = -1; - -InputStream.DRAIN = -2; - -InputStream.prototype = { - slice: function() { - if(this.start >= this.data.length) { - if(!this.eof) throw InputStream.DRAIN; - return InputStream.EOF; - } - return this.data.slice(this.start, this.data.length); - }, - char: function() { - if(!this.eof && this.start >= this.data.length - 1) throw InputStream.DRAIN; - if(this.start >= this.data.length) { - return InputStream.EOF; - } - var ch = this.data[this.start++]; - if (ch === '\r') - ch = '\n'; - return ch; - }, - advance: function(amount) { - this.start += amount; - if(this.start >= this.data.length) { - if(!this.eof) throw InputStream.DRAIN; - return InputStream.EOF; - } else { - if(this.committed > this.data.length / 2) { - // Sliiiide - this.lastLocation = this.location(); - this.data = this.data.slice(this.committed); - this.start = this.start - this.committed; - this.committed = 0; - } - } - }, - matchWhile: function(re) { - if(this.eof && this.start >= this.data.length ) return ''; - var r = new RegExp("^"+re+"+"); - var m = r.exec(this.slice()); - if(m) { - if(!this.eof && m[0].length == this.data.length - this.start) throw InputStream.DRAIN; - this.advance(m[0].length); - return m[0]; - } else { - return ''; - } - }, - matchUntil: function(re) { - var m, s; - s = this.slice(); - if(s === InputStream.EOF) { - return ''; - } else if(m = new RegExp(re + (this.eof ? "|$" : "")).exec(s)) { - var t = this.data.slice(this.start, this.start + m.index); - this.advance(m.index); - return t.replace(/\r/g, '\n').replace(/\n{2,}/g, '\n'); - } else { - throw InputStream.DRAIN; - } - }, - append: function(data) { - this.data += data; - }, - shift: function(n) { - if(!this.eof && this.start + n >= this.data.length) throw InputStream.DRAIN; - if(this.eof && this.start >= this.data.length) return InputStream.EOF; - var d = this.data.slice(this.start, this.start + n).toString(); - this.advance(Math.min(n, this.data.length - this.start)); - return d; - }, - peek: function(n) { - if(!this.eof && this.start + n >= this.data.length) throw InputStream.DRAIN; - if(this.eof && this.start >= this.data.length) return InputStream.EOF; - return this.data.slice(this.start, Math.min(this.start + n, this.data.length)).toString(); - }, - length: function() { - return this.data.length - this.start - 1; - }, - unget: function(d) { - if(d === InputStream.EOF) return; - this.start -= (d.length); - }, - undo: function() { - this.start = this.committed; - }, - commit: function() { - this.committed = this.start; - }, - location: function() { - var lastLine = this.lastLocation.line; - var lastColumn = this.lastLocation.column; - var read = this.data.slice(0, this.committed); - var newlines = read.match(/\n/g); - var line = newlines ? lastLine + newlines.length : lastLine; - var column = newlines ? read.length - read.lastIndexOf('\n') - 1 : lastColumn + read.length; - return {line: line, column: column}; - } -}; - -exports.InputStream = InputStream; - -}, -{}], -4:[function(_dereq_,module,exports){ -var SpecialElements = { - "http://www.w3.org/1999/xhtml": [ - 'address', - 'applet', - 'area', - 'article', - 'aside', - 'base', - 'basefont', - 'bgsound', - 'blockquote', - 'body', - 'br', - 'button', - 'caption', - 'center', - 'col', - 'colgroup', - 'dd', - 'details', - 'dir', - 'div', - 'dl', - 'dt', - 'embed', - 'fieldset', - 'figcaption', - 'figure', - 'footer', - 'form', - 'frame', - 'frameset', - 'h1', - 'h2', - 'h3', - 'h4', - 'h5', - 'h6', - 'head', - 'header', - 'hgroup', - 'hr', - 'html', - 'iframe', - 'img', - 'input', - 'isindex', - 'li', - 'link', - 'listing', - 'main', - 'marquee', - 'menu', - 'menuitem', - 'meta', - 'nav', - 'noembed', - 'noframes', - 'noscript', - 'object', - 'ol', - 'p', - 'param', - 'plaintext', - 'pre', - 'script', - 'section', - 'select', - 'source', - 'style', - 'summary', - 'table', - 'tbody', - 'td', - 'textarea', - 'tfoot', - 'th', - 'thead', - 'title', - 'tr', - 'track', - 'ul', - 'wbr', - 'xmp' - ], - "http://www.w3.org/1998/Math/MathML": [ - 'mi', - 'mo', - 'mn', - 'ms', - 'mtext', - 'annotation-xml' - ], - "http://www.w3.org/2000/svg": [ - 'foreignObject', - 'desc', - 'title' - ] -}; - - -function StackItem(namespaceURI, localName, attributes, node) { - this.localName = localName; - this.namespaceURI = namespaceURI; - this.attributes = attributes; - this.node = node; -} - -// http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#special -StackItem.prototype.isSpecial = function() { - return this.namespaceURI in SpecialElements && - SpecialElements[this.namespaceURI].indexOf(this.localName) > -1; -}; - -StackItem.prototype.isFosterParenting = function() { - if (this.namespaceURI === "http://www.w3.org/1999/xhtml") { - return this.localName === 'table' || - this.localName === 'tbody' || - this.localName === 'tfoot' || - this.localName === 'thead' || - this.localName === 'tr'; - } - return false; -}; - -StackItem.prototype.isNumberedHeader = function() { - if (this.namespaceURI === "http://www.w3.org/1999/xhtml") { - return this.localName === 'h1' || - this.localName === 'h2' || - this.localName === 'h3' || - this.localName === 'h4' || - this.localName === 'h5' || - this.localName === 'h6'; - } - return false; -}; - -StackItem.prototype.isForeign = function() { - return this.namespaceURI != "http://www.w3.org/1999/xhtml"; -}; - -function getAttribute(item, name) { - for (var i = 0; i < item.attributes.length; i++) { - if (item.attributes[i].nodeName == name) - return item.attributes[i].nodeValue; - } - return null; -} - -StackItem.prototype.isHtmlIntegrationPoint = function() { - if (this.namespaceURI === "http://www.w3.org/1998/Math/MathML") { - if (this.localName !== "annotation-xml") - return false; - var encoding = getAttribute(this, 'encoding'); - if (!encoding) - return false; - encoding = encoding.toLowerCase(); - return encoding === "text/html" || encoding === "application/xhtml+xml"; - } - if (this.namespaceURI === "http://www.w3.org/2000/svg") { - return this.localName === "foreignObject" - || this.localName === "desc" - || this.localName === "title"; - } - return false; -}; - -StackItem.prototype.isMathMLTextIntegrationPoint = function() { - if (this.namespaceURI === "http://www.w3.org/1998/Math/MathML") { - return this.localName === "mi" - || this.localName === "mo" - || this.localName === "mn" - || this.localName === "ms" - || this.localName === "mtext"; - } - return false; -}; - -exports.StackItem = StackItem; - -}, -{}], -5:[function(_dereq_,module,exports){ -var InputStream = _dereq_('./InputStream').InputStream; -var EntityParser = _dereq_('./EntityParser').EntityParser; - -function isWhitespace(c){ - return c === " " || c === "\n" || c === "\t" || c === "\r" || c === "\f"; -} - -function isAlpha(c) { - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); -} - -/** - * - * @param {Object} tokenHandler - * @constructor - */ -function Tokenizer(tokenHandler) { - this._tokenHandler = tokenHandler; - this._state = Tokenizer.DATA; - this._inputStream = new InputStream(); - this._currentToken = null; - this._temporaryBuffer = ''; - this._additionalAllowedCharacter = ''; -} - -Tokenizer.prototype._parseError = function(code, args) { - this._tokenHandler.parseError(code, args); -}; - -Tokenizer.prototype._emitToken = function(token) { - if (token.type === 'StartTag') { - for (var i = 1; i < token.data.length; i++) { - if (!token.data[i].nodeName) - token.data.splice(i--, 1); - } - } else if (token.type === 'EndTag') { - if (token.selfClosing) { - this._parseError('self-closing-flag-on-end-tag'); - } - if (token.data.length !== 0) { - this._parseError('attributes-in-end-tag'); - } - } - this._tokenHandler.processToken(token); - if (token.type === 'StartTag' && token.selfClosing && !this._tokenHandler.isSelfClosingFlagAcknowledged()) { - this._parseError('non-void-element-with-trailing-solidus', {name: token.name}); - } -}; - -Tokenizer.prototype._emitCurrentToken = function() { - this._state = Tokenizer.DATA; - this._emitToken(this._currentToken); -}; - -Tokenizer.prototype._currentAttribute = function() { - return this._currentToken.data[this._currentToken.data.length - 1]; -}; - -Tokenizer.prototype.setState = function(state) { - this._state = state; -}; - -Tokenizer.prototype.tokenize = function(source) { - // FIXME proper tokenizer states - Tokenizer.DATA = data_state; - Tokenizer.RCDATA = rcdata_state; - Tokenizer.RAWTEXT = rawtext_state; - Tokenizer.SCRIPT_DATA = script_data_state; - Tokenizer.PLAINTEXT = plaintext_state; - - - this._state = Tokenizer.DATA; - - this._inputStream.append(source); - - this._tokenHandler.startTokenization(this); - - this._inputStream.eof = true; - - var tokenizer = this; - - while (this._state.call(this, this._inputStream)); - - - function data_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._emitToken({type: 'EOF', data: null}); - return false; - } else if (data === '&') { - tokenizer.setState(character_reference_in_data_state); - } else if (data === '<') { - tokenizer.setState(tag_open_state); - } else if (data === '\u0000') { - tokenizer._emitToken({type: 'Characters', data: data}); - buffer.commit(); - } else { - var chars = buffer.matchUntil("&|<|\u0000"); - tokenizer._emitToken({type: 'Characters', data: data + chars}); - buffer.commit(); - } - return true; - } - - function character_reference_in_data_state(buffer) { - var character = EntityParser.consumeEntity(buffer, tokenizer); - tokenizer.setState(data_state); - tokenizer._emitToken({type: 'Characters', data: character || '&'}); - return true; - } - - function rcdata_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._emitToken({type: 'EOF', data: null}); - return false; - } else if (data === '&') { - tokenizer.setState(character_reference_in_rcdata_state); - } else if (data === '<') { - tokenizer.setState(rcdata_less_than_sign_state); - } else if (data === "\u0000") { - tokenizer._parseError("invalid-codepoint"); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - buffer.commit(); - } else { - var chars = buffer.matchUntil("&|<|\u0000"); - tokenizer._emitToken({type: 'Characters', data: data + chars}); - buffer.commit(); - } - return true; - } - - function character_reference_in_rcdata_state(buffer) { - var character = EntityParser.consumeEntity(buffer, tokenizer); - tokenizer.setState(rcdata_state); - tokenizer._emitToken({type: 'Characters', data: character || '&'}); - return true; - } - - function rawtext_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._emitToken({type: 'EOF', data: null}); - return false; - } else if (data === '<') { - tokenizer.setState(rawtext_less_than_sign_state); - } else if (data === "\u0000") { - tokenizer._parseError("invalid-codepoint"); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - buffer.commit(); - } else { - var chars = buffer.matchUntil("<|\u0000"); - tokenizer._emitToken({type: 'Characters', data: data + chars}); - } - return true; - } - - function plaintext_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._emitToken({type: 'EOF', data: null}); - return false; - } else if (data === "\u0000") { - tokenizer._parseError("invalid-codepoint"); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - buffer.commit(); - } else { - var chars = buffer.matchUntil("\u0000"); - tokenizer._emitToken({type: 'Characters', data: data + chars}); - } - return true; - } - - - function script_data_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._emitToken({type: 'EOF', data: null}); - return false; - } else if (data === '<') { - tokenizer.setState(script_data_less_than_sign_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - buffer.commit(); - } else { - var chars = buffer.matchUntil("<|\u0000"); - tokenizer._emitToken({type: 'Characters', data: data + chars}); - } - return true; - } - - function rcdata_less_than_sign_state(buffer) { - var data = buffer.char(); - if (data === "/") { - this._temporaryBuffer = ''; - tokenizer.setState(rcdata_end_tag_open_state); - } else { - tokenizer._emitToken({type: 'Characters', data: '<'}); - buffer.unget(data); - tokenizer.setState(rcdata_state); - } - return true; - } - - function rcdata_end_tag_open_state(buffer) { - var data = buffer.char(); - if (isAlpha(data)) { - this._temporaryBuffer += data; - tokenizer.setState(rcdata_end_tag_name_state); - } else { - tokenizer._emitToken({type: 'Characters', data: '' && appropriate) { - tokenizer._currentToken = {type: 'EndTag', name: this._temporaryBuffer, data: [], selfClosing: false}; - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else if (isAlpha(data)) { - this._temporaryBuffer += data; - buffer.commit(); - } else { - tokenizer._emitToken({type: 'Characters', data: '' && appropriate) { - tokenizer._currentToken = {type: 'EndTag', name: this._temporaryBuffer, data: [], selfClosing: false}; - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else if (isAlpha(data)) { - this._temporaryBuffer += data; - buffer.commit(); - } else { - tokenizer._emitToken({type: 'Characters', data: '' && appropriate) { - tokenizer._currentToken = {type: 'EndTag', name: 'script', data: [], selfClosing: false}; - tokenizer._emitCurrentToken(); - } else if (isAlpha(data)) { - this._temporaryBuffer += data; - buffer.commit(); - } else { - tokenizer._emitToken({type: 'Characters', data: '') { - tokenizer._emitToken({type: 'Characters', data: '>'}); - tokenizer.setState(script_data_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - tokenizer.setState(script_data_escaped_state); - } else { - tokenizer._emitToken({type: 'Characters', data: data}); - tokenizer.setState(script_data_escaped_state); - } - return true; - } - - function script_data_escaped_less_then_sign_state(buffer) { - var data = buffer.char(); - if (data === '/') { - this._temporaryBuffer = ''; - tokenizer.setState(script_data_escaped_end_tag_open_state); - } else if (isAlpha(data)) { - tokenizer._emitToken({type: 'Characters', data: '<' + data}); - this._temporaryBuffer = data; - tokenizer.setState(script_data_double_escape_start_state); - } else { - tokenizer._emitToken({type: 'Characters', data: '<'}); - buffer.unget(data); - tokenizer.setState(script_data_escaped_state); - } - return true; - } - - function script_data_escaped_end_tag_open_state(buffer) { - var data = buffer.char(); - if (isAlpha(data)) { - this._temporaryBuffer = data; - tokenizer.setState(script_data_escaped_end_tag_name_state); - } else { - tokenizer._emitToken({type: 'Characters', data: '' && appropriate) { - tokenizer._currentToken = {type: 'EndTag', name: 'script', data: [], selfClosing: false}; - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isAlpha(data)) { - this._temporaryBuffer += data; - buffer.commit(); - } else { - tokenizer._emitToken({type: 'Characters', data: '') { - tokenizer._emitToken({type: 'Characters', data: data}); - if (this._temporaryBuffer.toLowerCase() === 'script') - tokenizer.setState(script_data_double_escaped_state); - else - tokenizer.setState(script_data_escaped_state); - } else if (isAlpha(data)) { - tokenizer._emitToken({type: 'Characters', data: data}); - this._temporaryBuffer += data; - buffer.commit(); - } else { - buffer.unget(data); - tokenizer.setState(script_data_escaped_state); - } - return true; - } - - function script_data_double_escaped_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError('eof-in-script'); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer._emitToken({type: 'Characters', data: '-'}); - tokenizer.setState(script_data_double_escaped_dash_state); - } else if (data === '<') { - tokenizer._emitToken({type: 'Characters', data: '<'}); - tokenizer.setState(script_data_double_escaped_less_than_sign_state); - } else if (data === '\u0000') { - tokenizer._parseError('invalid-codepoint'); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - buffer.commit(); - } else { - tokenizer._emitToken({type: 'Characters', data: data}); - buffer.commit(); - } - return true; - } - - function script_data_double_escaped_dash_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError('eof-in-script'); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer._emitToken({type: 'Characters', data: '-'}); - tokenizer.setState(script_data_double_escaped_dash_dash_state); - } else if (data === '<') { - tokenizer._emitToken({type: 'Characters', data: '<'}); - tokenizer.setState(script_data_double_escaped_less_than_sign_state); - } else if (data === '\u0000') { - tokenizer._parseError('invalid-codepoint'); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - tokenizer.setState(script_data_double_escaped_state); - } else { - tokenizer._emitToken({type: 'Characters', data: data}); - tokenizer.setState(script_data_double_escaped_state); - } - return true; - } - - function script_data_double_escaped_dash_dash_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError('eof-in-script'); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer._emitToken({type: 'Characters', data: '-'}); - buffer.commit(); - } else if (data === '<') { - tokenizer._emitToken({type: 'Characters', data: '<'}); - tokenizer.setState(script_data_double_escaped_less_than_sign_state); - } else if (data === '>') { - tokenizer._emitToken({type: 'Characters', data: '>'}); - tokenizer.setState(script_data_state); - } else if (data === '\u0000') { - tokenizer._parseError('invalid-codepoint'); - tokenizer._emitToken({type: 'Characters', data: '\uFFFD'}); - tokenizer.setState(script_data_double_escaped_state); - } else { - tokenizer._emitToken({type: 'Characters', data: data}); - tokenizer.setState(script_data_double_escaped_state); - } - return true; - } - - function script_data_double_escaped_less_than_sign_state(buffer) { - var data = buffer.char(); - if (data === '/') { - tokenizer._emitToken({type: 'Characters', data: '/'}); - this._temporaryBuffer = ''; - tokenizer.setState(script_data_double_escape_end_state); - } else { - buffer.unget(data); - tokenizer.setState(script_data_double_escaped_state); - } - return true; - } - - function script_data_double_escape_end_state(buffer) { - var data = buffer.char(); - if (isWhitespace(data) || data === '/' || data === '>') { - tokenizer._emitToken({type: 'Characters', data: data}); - if (this._temporaryBuffer.toLowerCase() === 'script') - tokenizer.setState(script_data_escaped_state); - else - tokenizer.setState(script_data_double_escaped_state); - } else if (isAlpha(data)) { - tokenizer._emitToken({type: 'Characters', data: data}); - this._temporaryBuffer += data; - buffer.commit(); - } else { - buffer.unget(data); - tokenizer.setState(script_data_double_escaped_state); - } - return true; - } - - function tag_open_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("bare-less-than-sign-at-eof"); - tokenizer._emitToken({type: 'Characters', data: '<'}); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isAlpha(data)) { - tokenizer._currentToken = {type: 'StartTag', name: data.toLowerCase(), data: []}; - tokenizer.setState(tag_name_state); - } else if (data === '!') { - tokenizer.setState(markup_declaration_open_state); - } else if (data === '/') { - tokenizer.setState(close_tag_open_state); - } else if (data === '>') { - // XXX In theory it could be something besides a tag name. But - // do we really care? - tokenizer._parseError("expected-tag-name-but-got-right-bracket"); - tokenizer._emitToken({type: 'Characters', data: "<>"}); - tokenizer.setState(data_state); - } else if (data === '?') { - // XXX In theory it could be something besides a tag name. But - // do we really care? - tokenizer._parseError("expected-tag-name-but-got-question-mark"); - buffer.unget(data); - tokenizer.setState(bogus_comment_state); - } else { - // XXX - tokenizer._parseError("expected-tag-name"); - tokenizer._emitToken({type: 'Characters', data: "<"}); - buffer.unget(data); - tokenizer.setState(data_state); - } - return true; - } - - function close_tag_open_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("expected-closing-tag-but-got-eof"); - tokenizer._emitToken({type: 'Characters', data: '') { - tokenizer._parseError("expected-closing-tag-but-got-right-bracket"); - tokenizer.setState(data_state); - } else { - tokenizer._parseError("expected-closing-tag-but-got-char", {data: data}); // param 1 is datavars: - buffer.unget(data); - tokenizer.setState(bogus_comment_state); - } - return true; - } - - function tag_name_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError('eof-in-tag-name'); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - tokenizer.setState(before_attribute_name_state); - } else if (isAlpha(data)) { - tokenizer._currentToken.name += data.toLowerCase(); - } else if (data === '>') { - tokenizer._emitCurrentToken(); - } else if (data === '/') { - tokenizer.setState(self_closing_tag_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.name += "\uFFFD"; - } else { - tokenizer._currentToken.name += data; - } - buffer.commit(); - - return true; - } - - function before_attribute_name_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("expected-attribute-name-but-got-eof"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - return true; - } else if (isAlpha(data)) { - tokenizer._currentToken.data.push({nodeName: data.toLowerCase(), nodeValue: ""}); - tokenizer.setState(attribute_name_state); - } else if (data === '>') { - tokenizer._emitCurrentToken(); - } else if (data === '/') { - tokenizer.setState(self_closing_tag_state); - } else if (data === "'" || data === '"' || data === '=' || data === '<') { - tokenizer._parseError("invalid-character-in-attribute-name"); - tokenizer._currentToken.data.push({nodeName: data, nodeValue: ""}); - tokenizer.setState(attribute_name_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data.push({nodeName: "\uFFFD", nodeValue: ""}); - } else { - tokenizer._currentToken.data.push({nodeName: data, nodeValue: ""}); - tokenizer.setState(attribute_name_state); - } - return true; - } - - function attribute_name_state(buffer) { - var data = buffer.char(); - var leavingThisState = true; - var shouldEmit = false; - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-attribute-name"); - buffer.unget(data); - tokenizer.setState(data_state); - shouldEmit = true; - } else if (data === '=') { - tokenizer.setState(before_attribute_value_state); - } else if (isAlpha(data)) { - tokenizer._currentAttribute().nodeName += data.toLowerCase(); - leavingThisState = false; - } else if (data === '>') { - // XXX If we emit here the attributes are converted to a dict - // without being checked and when the code below runs we error - // because data is a dict not a list - shouldEmit = true; - } else if (isWhitespace(data)) { - tokenizer.setState(after_attribute_name_state); - } else if (data === '/') { - tokenizer.setState(self_closing_tag_state); - } else if (data === "'" || data === '"') { - tokenizer._parseError("invalid-character-in-attribute-name"); - tokenizer._currentAttribute().nodeName += data; - leavingThisState = false; - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentAttribute().nodeName += "\uFFFD"; - } else { - tokenizer._currentAttribute().nodeName += data; - leavingThisState = false; - } - - if (leavingThisState) { - // Attributes are not dropped at this stage. That happens when the - // start tag token is emitted so values can still be safely appended - // to attributes, but we do want to report the parse error in time. - var attributes = tokenizer._currentToken.data; - var currentAttribute = attributes[attributes.length - 1]; - for (var i = attributes.length - 2; i >= 0; i--) { - if (currentAttribute.nodeName === attributes[i].nodeName) { - tokenizer._parseError("duplicate-attribute", {name: currentAttribute.nodeName}); - currentAttribute.nodeName = null; - break; - } - } - if (shouldEmit) - tokenizer._emitCurrentToken(); - } else { - buffer.commit(); - } - return true; - } - - function after_attribute_name_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("expected-end-of-tag-but-got-eof"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - return true; - } else if (data === '=') { - tokenizer.setState(before_attribute_value_state); - } else if (data === '>') { - tokenizer._emitCurrentToken(); - } else if (isAlpha(data)) { - tokenizer._currentToken.data.push({nodeName: data, nodeValue: ""}); - tokenizer.setState(attribute_name_state); - } else if (data === '/') { - tokenizer.setState(self_closing_tag_state); - } else if (data === "'" || data === '"' || data === '<') { - tokenizer._parseError("invalid-character-after-attribute-name"); - tokenizer._currentToken.data.push({nodeName: data, nodeValue: ""}); - tokenizer.setState(attribute_name_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data.push({nodeName: "\uFFFD", nodeValue: ""}); - } else { - tokenizer._currentToken.data.push({nodeName: data, nodeValue: ""}); - tokenizer.setState(attribute_name_state); - } - return true; - } - - function before_attribute_value_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("expected-attribute-value-but-got-eof"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - return true; - } else if (data === '"') { - tokenizer.setState(attribute_value_double_quoted_state); - } else if (data === '&') { - tokenizer.setState(attribute_value_unquoted_state); - buffer.unget(data); - } else if (data === "'") { - tokenizer.setState(attribute_value_single_quoted_state); - } else if (data === '>') { - tokenizer._parseError("expected-attribute-value-but-got-right-bracket"); - tokenizer._emitCurrentToken(); - } else if (data === '=' || data === '<' || data === '`') { - tokenizer._parseError("unexpected-character-in-unquoted-attribute-value"); - tokenizer._currentAttribute().nodeValue += data; - tokenizer.setState(attribute_value_unquoted_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentAttribute().nodeValue += "\uFFFD"; - } else { - tokenizer._currentAttribute().nodeValue += data; - tokenizer.setState(attribute_value_unquoted_state); - } - - return true; - } - - function attribute_value_double_quoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-attribute-value-double-quote"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '"') { - tokenizer.setState(after_attribute_value_state); - } else if (data === '&') { - this._additionalAllowedCharacter = '"'; - tokenizer.setState(character_reference_in_attribute_value_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentAttribute().nodeValue += "\uFFFD"; - } else { - var s = buffer.matchUntil('[\0"&]'); - data = data + s; - tokenizer._currentAttribute().nodeValue += data; - } - return true; - } - - function attribute_value_single_quoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-attribute-value-single-quote"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === "'") { - tokenizer.setState(after_attribute_value_state); - } else if (data === '&') { - this._additionalAllowedCharacter = "'"; - tokenizer.setState(character_reference_in_attribute_value_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentAttribute().nodeValue += "\uFFFD"; - } else { - tokenizer._currentAttribute().nodeValue += data + buffer.matchUntil("\u0000|['&]"); - } - return true; - } - - function attribute_value_unquoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-after-attribute-value"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - tokenizer.setState(before_attribute_name_state); - } else if (data === '&') { - this._additionalAllowedCharacter = ">"; - tokenizer.setState(character_reference_in_attribute_value_state); - } else if (data === '>') { - tokenizer._emitCurrentToken(); - } else if (data === '"' || data === "'" || data === '=' || data === '`' || data === '<') { - tokenizer._parseError("unexpected-character-in-unquoted-attribute-value"); - tokenizer._currentAttribute().nodeValue += data; - buffer.commit(); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentAttribute().nodeValue += "\uFFFD"; - } else { - var o = buffer.matchUntil("\u0000|["+ "\t\n\v\f\x20\r" + "&<>\"'=`" +"]"); - if (o === InputStream.EOF) { - tokenizer._parseError("eof-in-attribute-value-no-quotes"); - tokenizer._emitCurrentToken(); - } - // Commit here since this state is re-enterable and its outcome won't change with more data. - buffer.commit(); - tokenizer._currentAttribute().nodeValue += data + o; - } - return true; - } - - function character_reference_in_attribute_value_state(buffer) { - var character = EntityParser.consumeEntity(buffer, tokenizer, this._additionalAllowedCharacter); - this._currentAttribute().nodeValue += character || '&'; - // We're supposed to switch back to the attribute value state that - // we were in when we were switched into this state. Rather than - // keeping track of this explictly, we observe that the previous - // state can be determined by additionalAllowedCharacter. - if (this._additionalAllowedCharacter === '"') - tokenizer.setState(attribute_value_double_quoted_state); - else if (this._additionalAllowedCharacter === '\'') - tokenizer.setState(attribute_value_single_quoted_state); - else if (this._additionalAllowedCharacter === '>') - tokenizer.setState(attribute_value_unquoted_state); - return true; - } - - function after_attribute_value_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-after-attribute-value"); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - tokenizer.setState(before_attribute_name_state); - } else if (data === '>') { - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (data === '/') { - tokenizer.setState(self_closing_tag_state); - } else { - tokenizer._parseError("unexpected-character-after-attribute-value"); - buffer.unget(data); - tokenizer.setState(before_attribute_name_state); - } - return true; - } - - function self_closing_tag_state(buffer) { - var c = buffer.char(); - if (c === InputStream.EOF) { - tokenizer._parseError("unexpected-eof-after-solidus-in-tag"); - buffer.unget(c); - tokenizer.setState(data_state); - } else if (c === '>') { - tokenizer._currentToken.selfClosing = true; - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - tokenizer._parseError("unexpected-character-after-solidus-in-tag"); - buffer.unget(c); - tokenizer.setState(before_attribute_name_state); - } - return true; - } - - function bogus_comment_state(buffer) { - var data = buffer.matchUntil('>'); - data = data.replace(/\u0000/g, "\uFFFD"); - buffer.char(); - tokenizer._emitToken({type: 'Comment', data: data}); - tokenizer.setState(data_state); - return true; - } - - function markup_declaration_open_state(buffer) { - var chars = buffer.shift(2); - if (chars === '--') { - tokenizer._currentToken = {type: 'Comment', data: ''}; - tokenizer.setState(comment_start_state); - } else { - var newchars = buffer.shift(5); - if (newchars === InputStream.EOF || chars === InputStream.EOF) { - tokenizer._parseError("expected-dashes-or-doctype"); - tokenizer.setState(bogus_comment_state); - buffer.unget(chars); - return true; - } - - chars += newchars; - if (chars.toUpperCase() === 'DOCTYPE') { - tokenizer._currentToken = {type: 'Doctype', name: '', publicId: null, systemId: null, forceQuirks: false}; - tokenizer.setState(doctype_state); - } else if (tokenizer._tokenHandler.isCdataSectionAllowed() && chars === '[CDATA[') { - tokenizer.setState(cdata_section_state); - } else { - tokenizer._parseError("expected-dashes-or-doctype"); - buffer.unget(chars); - tokenizer.setState(bogus_comment_state); - } - } - return true; - } - - function cdata_section_state(buffer) { - var data = buffer.matchUntil(']]>'); - // skip ]]> - buffer.shift(3); - if (data) { - tokenizer._emitToken({type: 'Characters', data: data}); - } - tokenizer.setState(data_state); - return true; - } - - function comment_start_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-comment"); - tokenizer._emitToken(tokenizer._currentToken); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer.setState(comment_start_dash_state); - } else if (data === '>') { - tokenizer._parseError("incorrect-comment"); - tokenizer._emitToken(tokenizer._currentToken); - tokenizer.setState(data_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data += "\uFFFD"; - } else { - tokenizer._currentToken.data += data; - tokenizer.setState(comment_state); - } - return true; - } - - function comment_start_dash_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-comment"); - tokenizer._emitToken(tokenizer._currentToken); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer.setState(comment_end_state); - } else if (data === '>') { - tokenizer._parseError("incorrect-comment"); - tokenizer._emitToken(tokenizer._currentToken); - tokenizer.setState(data_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data += "\uFFFD"; - } else { - tokenizer._currentToken.data += '-' + data; - tokenizer.setState(comment_state); - } - return true; - } - - function comment_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-comment"); - tokenizer._emitToken(tokenizer._currentToken); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer.setState(comment_end_dash_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data += "\uFFFD"; - } else { - tokenizer._currentToken.data += data; - buffer.commit(); - } - return true; - } - - function comment_end_dash_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-comment-end-dash"); - tokenizer._emitToken(tokenizer._currentToken); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer.setState(comment_end_state); - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data += "-\uFFFD"; - tokenizer.setState(comment_state); - } else { - tokenizer._currentToken.data += '-' + data + buffer.matchUntil('\u0000|-'); - // Consume the next character which is either a "-" or an :EOF as - // well so if there's a "-" directly after the "-" we go nicely to - // the "comment end state" without emitting a tokenizer._parseError there. - buffer.char(); - } - return true; - } - - function comment_end_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-comment-double-dash"); - tokenizer._emitToken(tokenizer._currentToken); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '>') { - tokenizer._emitToken(tokenizer._currentToken); - tokenizer.setState(data_state); - } else if (data === '!') { - tokenizer._parseError("unexpected-bang-after-double-dash-in-comment"); - tokenizer.setState(comment_end_bang_state); - } else if (data === '-') { - tokenizer._parseError("unexpected-dash-after-double-dash-in-comment"); - tokenizer._currentToken.data += data; - } else if (data === '\u0000') { - tokenizer._parseError("invalid-codepoint"); - tokenizer._currentToken.data += "--\uFFFD"; - tokenizer.setState(comment_state); - } else { - // XXX - tokenizer._parseError("unexpected-char-in-comment"); - tokenizer._currentToken.data += '--' + data; - tokenizer.setState(comment_state); - } - return true; - } - - function comment_end_bang_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-comment-end-bang-state"); - tokenizer._emitToken(tokenizer._currentToken); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '>') { - tokenizer._emitToken(tokenizer._currentToken); - tokenizer.setState(data_state); - } else if (data === '-') { - tokenizer._currentToken.data += '--!'; - tokenizer.setState(comment_end_dash_state); - } else { - tokenizer._currentToken.data += '--!' + data; - tokenizer.setState(comment_state); - } - return true; - } - - function doctype_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("expected-doctype-name-but-got-eof"); - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isWhitespace(data)) { - tokenizer.setState(before_doctype_name_state); - } else { - tokenizer._parseError("need-space-after-doctype"); - buffer.unget(data); - tokenizer.setState(before_doctype_name_state); - } - return true; - } - - function before_doctype_name_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("expected-doctype-name-but-got-eof"); - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isWhitespace(data)) { - // pass - } else if (data === '>') { - tokenizer._parseError("expected-doctype-name-but-got-right-bracket"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - if (isAlpha(data)) - data = data.toLowerCase(); - tokenizer._currentToken.name = data; - tokenizer.setState(doctype_name_state); - } - return true; - } - - function doctype_name_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer._parseError("eof-in-doctype-name"); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isWhitespace(data)) { - tokenizer.setState(after_doctype_name_state); - } else if (data === '>') { - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - if (isAlpha(data)) - data = data.toLowerCase(); - tokenizer._currentToken.name += data; - buffer.commit(); - } - return true; - } - - function after_doctype_name_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer._parseError("eof-in-doctype"); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isWhitespace(data)) { - // pass - } else if (data === '>') { - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - if (['p', 'P'].indexOf(data) > -1) { - var expected = [['u', 'U'], ['b', 'B'], ['l', 'L'], ['i', 'I'], ['c', 'C']]; - var matched = expected.every(function(expected){ - data = buffer.char(); - return expected.indexOf(data) > -1; - }); - if (matched) { - tokenizer.setState(after_doctype_public_keyword_state); - return true; - } - } else if (['s', 'S'].indexOf(data) > -1) { - var expected = [['y', 'Y'], ['s', 'S'], ['t', 'T'], ['e', 'E'], ['m', 'M']]; - var matched = expected.every(function(expected){ - data = buffer.char(); - return expected.indexOf(data) > -1; - }); - if (matched) { - tokenizer.setState(after_doctype_system_keyword_state); - return true; - } - } - - // All the characters read before the current 'data' will be - // [a-zA-Z], so they're garbage in the bogus doctype and can be - // discarded; only the latest character might be '>' or EOF - // and needs to be ungetted - buffer.unget(data); - tokenizer._currentToken.forceQuirks = true; - - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - tokenizer._parseError("expected-space-or-right-bracket-in-doctype", {data: data}); - tokenizer.setState(bogus_doctype_state); - } - } - return true; - } - - function after_doctype_public_keyword_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isWhitespace(data)) { - tokenizer.setState(before_doctype_public_identifier_state); - } else if (data === "'" || data === '"') { - tokenizer._parseError("unexpected-char-in-doctype"); - buffer.unget(data); - tokenizer.setState(before_doctype_public_identifier_state); - } else { - buffer.unget(data); - tokenizer.setState(before_doctype_public_identifier_state); - } - return true; - } - - function before_doctype_public_identifier_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (isWhitespace(data)) { - // pass - } else if (data === '"') { - tokenizer._currentToken.publicId = ''; - tokenizer.setState(doctype_public_identifier_double_quoted_state); - } else if (data === "'") { - tokenizer._currentToken.publicId = ''; - tokenizer.setState(doctype_public_identifier_single_quoted_state); - } else if (data === '>') { - tokenizer._parseError("unexpected-end-of-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(bogus_doctype_state); - } - return true; - } - - function doctype_public_identifier_double_quoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (data === '"') { - tokenizer.setState(after_doctype_public_identifier_state); - } else if (data === '>') { - tokenizer._parseError("unexpected-end-of-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - tokenizer._currentToken.publicId += data; - } - return true; - } - - function doctype_public_identifier_single_quoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - buffer.unget(data); - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (data === "'") { - tokenizer.setState(after_doctype_public_identifier_state); - } else if (data === '>') { - tokenizer._parseError("unexpected-end-of-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else { - tokenizer._currentToken.publicId += data; - } - return true; - } - - function after_doctype_public_identifier_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - tokenizer.setState(between_doctype_public_and_system_identifiers_state); - } else if (data === '>') { - tokenizer.setState(data_state); - tokenizer._emitCurrentToken(); - } else if (data === '"') { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer._currentToken.systemId = ''; - tokenizer.setState(doctype_system_identifier_double_quoted_state); - } else if (data === "'") { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer._currentToken.systemId = ''; - tokenizer.setState(doctype_system_identifier_single_quoted_state); - } else { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(bogus_doctype_state); - } - return true; - } - - function between_doctype_public_and_system_identifiers_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - // pass - } else if (data === '>') { - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else if (data === '"') { - tokenizer._currentToken.systemId = ''; - tokenizer.setState(doctype_system_identifier_double_quoted_state); - } else if (data === "'") { - tokenizer._currentToken.systemId = ''; - tokenizer.setState(doctype_system_identifier_single_quoted_state); - } else { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(bogus_doctype_state); - } - return true; - } - - function after_doctype_system_keyword_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - tokenizer.setState(before_doctype_system_identifier_state); - } else if (data === "'" || data === '"') { - tokenizer._parseError("unexpected-char-in-doctype"); - buffer.unget(data); - tokenizer.setState(before_doctype_system_identifier_state); - } else { - buffer.unget(data); - tokenizer.setState(before_doctype_system_identifier_state); - } - return true; - } - - function before_doctype_system_identifier_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - // pass - } else if (data === '"') { - tokenizer._currentToken.systemId = ''; - tokenizer.setState(doctype_system_identifier_double_quoted_state); - } else if (data === "'") { - tokenizer._currentToken.systemId = ''; - tokenizer.setState(doctype_system_identifier_single_quoted_state); - } else if (data === '>') { - tokenizer._parseError("unexpected-end-of-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer.setState(bogus_doctype_state); - } - return true; - } - - function doctype_system_identifier_double_quoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === '"') { - tokenizer.setState(after_doctype_system_identifier_state); - } else if (data === '>') { - tokenizer._parseError("unexpected-end-of-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else { - tokenizer._currentToken.systemId += data; - } - return true; - } - - function doctype_system_identifier_single_quoted_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (data === "'") { - tokenizer.setState(after_doctype_system_identifier_state); - } else if (data === '>') { - tokenizer._parseError("unexpected-end-of-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else { - tokenizer._currentToken.systemId += data; - } - return true; - } - - function after_doctype_system_identifier_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - tokenizer._parseError("eof-in-doctype"); - tokenizer._currentToken.forceQuirks = true; - tokenizer._emitCurrentToken(); - buffer.unget(data); - tokenizer.setState(data_state); - } else if (isWhitespace(data)) { - // pass - } else if (data === '>') { - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else { - tokenizer._parseError("unexpected-char-in-doctype"); - tokenizer.setState(bogus_doctype_state); - } - return true; - } - - function bogus_doctype_state(buffer) { - var data = buffer.char(); - if (data === InputStream.EOF) { - buffer.unget(data); - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } else if (data === '>') { - tokenizer._emitCurrentToken(); - tokenizer.setState(data_state); - } - return true; - } -}; - -Object.defineProperty(Tokenizer.prototype, 'lineNumber', { - get: function() { - return this._inputStream.location().line; - } -}); - -Object.defineProperty(Tokenizer.prototype, 'columnNumber', { - get: function() { - return this._inputStream.location().column; - } -}); - -exports.Tokenizer = Tokenizer; - -}, -{"./EntityParser":2,"./InputStream":3}], -6:[function(_dereq_,module,exports){ -var assert = _dereq_('assert'); - -var messages = _dereq_('./messages.json'); -var constants = _dereq_('./constants'); - -var EventEmitter = _dereq_('events').EventEmitter; - -var Tokenizer = _dereq_('./Tokenizer').Tokenizer; -var ElementStack = _dereq_('./ElementStack').ElementStack; -var StackItem = _dereq_('./StackItem').StackItem; - -var Marker = {}; - -function isWhitespace(ch) { - return ch === " " || ch === "\n" || ch === "\t" || ch === "\r" || ch === "\f"; -} - -function isWhitespaceOrReplacementCharacter(ch) { - return isWhitespace(ch) || ch === '\uFFFD'; -} - -function isAllWhitespace(characters) { - for (var i = 0; i < characters.length; i++) { - var ch = characters[i]; - if (!isWhitespace(ch)) - return false; - } - return true; -} - -function isAllWhitespaceOrReplacementCharacters(characters) { - for (var i = 0; i < characters.length; i++) { - var ch = characters[i]; - if (!isWhitespaceOrReplacementCharacter(ch)) - return false; - } - return true; -} - -function getAttribute(node, name) { - for (var i = 0; i < node.attributes.length; i++) { - var attribute = node.attributes[i]; - if (attribute.nodeName === name) { - return attribute; - } - } - return null; -} - -function CharacterBuffer(characters) { - this.characters = characters; - this.current = 0; - this.end = this.characters.length; -} - -CharacterBuffer.prototype.skipAtMostOneLeadingNewline = function() { - if (this.characters[this.current] === '\n') - this.current++; -}; - -CharacterBuffer.prototype.skipLeadingWhitespace = function() { - while (isWhitespace(this.characters[this.current])) { - if (++this.current == this.end) - return; - } -}; - -CharacterBuffer.prototype.skipLeadingNonWhitespace = function() { - while (!isWhitespace(this.characters[this.current])) { - if (++this.current == this.end) - return; - } -}; - -CharacterBuffer.prototype.takeRemaining = function() { - return this.characters.substring(this.current); -}; - -CharacterBuffer.prototype.takeLeadingWhitespace = function() { - var start = this.current; - this.skipLeadingWhitespace(); - if (start === this.current) - return ""; - return this.characters.substring(start, this.current - start); -}; - -Object.defineProperty(CharacterBuffer.prototype, 'length', { - get: function(){ - return this.end - this.current; - } -}); - -/** - * - * @constructor - */ -function TreeBuilder() { - this.tokenizer = null; - this.errorHandler = null; - this.scriptingEnabled = false; - this.document = null; - this.head = null; - this.form = null; - this.openElements = new ElementStack(); - this.activeFormattingElements = []; - this.insertionMode = null; - this.insertionModeName = ""; - this.originalInsertionMode = ""; - this.inQuirksMode = false; // TODO quirks mode - this.compatMode = "no quirks"; - this.framesetOk = true; - this.redirectAttachToFosterParent = false; - this.selfClosingFlagAcknowledged = false; - this.context = ""; - this.pendingTableCharacters = []; - this.shouldSkipLeadingNewline = false; - - var tree = this; - var modes = this.insertionModes = {}; - modes.base = { - end_tag_handlers: {"-default": 'endTagOther'}, - start_tag_handlers: {"-default": 'startTagOther'}, - processEOF: function() { - tree.generateImpliedEndTags(); - if (tree.openElements.length > 2) { - tree.parseError('expected-closing-tag-but-got-eof'); - } else if (tree.openElements.length == 2 && - tree.openElements.item(1).localName != 'body') { - // This happens for framesets or something? - tree.parseError('expected-closing-tag-but-got-eof'); - } else if (tree.context && tree.openElements.length > 1) { - // XXX This is not what the specification says. Not sure what to do here. - //tree.parseError('eof-in-innerhtml'); - } - }, - processComment: function(data) { - // For most phases the following is forceQuirks. Where it's not it will be - // overridden. - tree.insertComment(data, tree.currentStackItem().node); - }, - processDoctype: function(name, publicId, systemId, forceQuirks) { - tree.parseError('unexpected-doctype'); - }, - processStartTag: function(name, attributes, selfClosing) { - if (this[this.start_tag_handlers[name]]) { - this[this.start_tag_handlers[name]](name, attributes, selfClosing); - } else if (this[this.start_tag_handlers["-default"]]) { - this[this.start_tag_handlers["-default"]](name, attributes, selfClosing); - } else { - throw(new Error("No handler found for "+name)); - } - }, - processEndTag: function(name) { - if (this[this.end_tag_handlers[name]]) { - this[this.end_tag_handlers[name]](name); - } else if (this[this.end_tag_handlers["-default"]]) { - this[this.end_tag_handlers["-default"]](name); - } else { - throw(new Error("No handler found for "+name)); - } - }, - startTagHtml: function(name, attributes) { - modes.inBody.startTagHtml(name, attributes); - } - }; - - modes.initial = Object.create(modes.base); - - modes.initial.processEOF = function() { - tree.parseError("expected-doctype-but-got-eof"); - this.anythingElse(); - tree.insertionMode.processEOF(); - }; - - modes.initial.processComment = function(data) { - tree.insertComment(data, tree.document); - }; - - modes.initial.processDoctype = function(name, publicId, systemId, forceQuirks) { - tree.insertDoctype(name || '', publicId || '', systemId || ''); - - if (forceQuirks || name != 'html' || (publicId != null && ([ - "+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//ietf//dtd html//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//", - "html" - ].some(publicIdStartsWith) - || [ - "-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html" - ].indexOf(publicId.toLowerCase()) > -1 - || (systemId == null && [ - "-//w3c//dtd html 4.01 transitional//", - "-//w3c//dtd html 4.01 frameset//" - ].some(publicIdStartsWith))) - ) - || (systemId != null && (systemId.toLowerCase() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd")) - ) { - tree.compatMode = "quirks"; - tree.parseError("quirky-doctype"); - } else if (publicId != null && ([ - "-//w3c//dtd xhtml 1.0 transitional//", - "-//w3c//dtd xhtml 1.0 frameset//" - ].some(publicIdStartsWith) - || (systemId != null && [ - "-//w3c//dtd html 4.01 transitional//", - "-//w3c//dtd html 4.01 frameset//" - ].indexOf(publicId.toLowerCase()) > -1)) - ) { - tree.compatMode = "limited quirks"; - tree.parseError("almost-standards-doctype"); - } else { - if ((publicId == "-//W3C//DTD HTML 4.0//EN" && (systemId == null || systemId == "http://www.w3.org/TR/REC-html40/strict.dtd")) - || (publicId == "-//W3C//DTD HTML 4.01//EN" && (systemId == null || systemId == "http://www.w3.org/TR/html4/strict.dtd")) - || (publicId == "-//W3C//DTD XHTML 1.0 Strict//EN" && (systemId == "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd")) - || (publicId == "-//W3C//DTD XHTML 1.1//EN" && (systemId == "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd")) - ) { - // warning - //tree.warn("obsolete-doctype"); - } else if (!((systemId == null || systemId == "about:legacy-compat") && publicId == null)) { - tree.parseError("unknown-doctype"); - } - } - tree.setInsertionMode('beforeHTML'); - function publicIdStartsWith(string) { - return publicId.toLowerCase().indexOf(string) === 0; - } - }; - - modes.initial.processCharacters = function(buffer) { - buffer.skipLeadingWhitespace(); - if (!buffer.length) - return; - tree.parseError('expected-doctype-but-got-chars'); - this.anythingElse(); - tree.insertionMode.processCharacters(buffer); - }; - - modes.initial.processStartTag = function(name, attributes, selfClosing) { - tree.parseError('expected-doctype-but-got-start-tag', {name: name}); - this.anythingElse(); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.initial.processEndTag = function(name) { - tree.parseError('expected-doctype-but-got-end-tag', {name: name}); - this.anythingElse(); - tree.insertionMode.processEndTag(name); - }; - - modes.initial.anythingElse = function() { - tree.compatMode = 'quirks'; - tree.setInsertionMode('beforeHTML'); - }; - - modes.beforeHTML = Object.create(modes.base); - - modes.beforeHTML.start_tag_handlers = { - html: 'startTagHtml', - '-default': 'startTagOther' - }; - - modes.beforeHTML.processEOF = function() { - this.anythingElse(); - tree.insertionMode.processEOF(); - }; - - modes.beforeHTML.processComment = function(data) { - tree.insertComment(data, tree.document); - }; - - modes.beforeHTML.processCharacters = function(buffer) { - buffer.skipLeadingWhitespace(); - if (!buffer.length) - return; - this.anythingElse(); - tree.insertionMode.processCharacters(buffer); - }; - - modes.beforeHTML.startTagHtml = function(name, attributes, selfClosing) { - tree.insertHtmlElement(attributes); - tree.setInsertionMode('beforeHead'); - }; - - modes.beforeHTML.startTagOther = function(name, attributes, selfClosing) { - this.anythingElse(); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.beforeHTML.processEndTag = function(name) { - this.anythingElse(); - tree.insertionMode.processEndTag(name); - }; - - modes.beforeHTML.anythingElse = function() { - tree.insertHtmlElement(); - tree.setInsertionMode('beforeHead'); - }; - - modes.afterAfterBody = Object.create(modes.base); - - modes.afterAfterBody.start_tag_handlers = { - html: 'startTagHtml', - '-default': 'startTagOther' - }; - - modes.afterAfterBody.processComment = function(data) { - tree.insertComment(data, tree.document); - }; - - modes.afterAfterBody.processDoctype = function(data) { - modes.inBody.processDoctype(data); - }; - - modes.afterAfterBody.startTagHtml = function(data, attributes) { - modes.inBody.startTagHtml(data, attributes); - }; - - modes.afterAfterBody.startTagOther = function(name, attributes, selfClosing) { - tree.parseError('unexpected-start-tag', {name: name}); - tree.setInsertionMode('inBody'); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.afterAfterBody.endTagOther = function(name) { - tree.parseError('unexpected-end-tag', {name: name}); - tree.setInsertionMode('inBody'); - tree.insertionMode.processEndTag(name); - }; - - modes.afterAfterBody.processCharacters = function(data) { - if (!isAllWhitespace(data.characters)) { - tree.parseError('unexpected-char-after-body'); - tree.setInsertionMode('inBody'); - return tree.insertionMode.processCharacters(data); - } - modes.inBody.processCharacters(data); - }; - - modes.afterBody = Object.create(modes.base); - - modes.afterBody.end_tag_handlers = { - html: 'endTagHtml', - '-default': 'endTagOther' - }; - - modes.afterBody.processComment = function(data) { - // This is needed because data is to be appended to the html element here - // and not to whatever is currently open. - tree.insertComment(data, tree.openElements.rootNode); - }; - - modes.afterBody.processCharacters = function(data) { - if (!isAllWhitespace(data.characters)) { - tree.parseError('unexpected-char-after-body'); - tree.setInsertionMode('inBody'); - return tree.insertionMode.processCharacters(data); - } - modes.inBody.processCharacters(data); - }; - - modes.afterBody.processStartTag = function(name, attributes, selfClosing) { - tree.parseError('unexpected-start-tag-after-body', {name: name}); - tree.setInsertionMode('inBody'); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.afterBody.endTagHtml = function(name) { - if (tree.context) { - tree.parseError('end-html-in-innerhtml'); - } else { - // XXX This may need to be done, not sure - // Don't set last_phase to the current phase but to the inBody phase - // instead. No need for extra parseErrors if there's something after - // . - // Try XX for instance - tree.setInsertionMode('afterAfterBody'); - } - }; - - modes.afterBody.endTagOther = function(name) { - tree.parseError('unexpected-end-tag-after-body', {name: name}); - tree.setInsertionMode('inBody'); - tree.insertionMode.processEndTag(name); - }; - - modes.afterFrameset = Object.create(modes.base); - - modes.afterFrameset.start_tag_handlers = { - html: 'startTagHtml', - noframes: 'startTagNoframes', - '-default': 'startTagOther' - }; - - modes.afterFrameset.end_tag_handlers = { - html: 'endTagHtml', - '-default': 'endTagOther' - }; - - modes.afterFrameset.processCharacters = function(buffer) { - var characters = buffer.takeRemaining(); - var whitespace = ""; - for (var i = 0; i < characters.length; i++) { - var ch = characters[i]; - if (isWhitespace(ch)) - whitespace += ch; - } - if (whitespace) { - tree.insertText(whitespace); - } - if (whitespace.length < characters.length) - tree.parseError('expected-eof-but-got-char'); - }; - - modes.afterFrameset.startTagNoframes = function(name, attributes) { - modes.inHead.processStartTag(name, attributes); - }; - - modes.afterFrameset.startTagOther = function(name, attributes) { - tree.parseError("unexpected-start-tag-after-frameset", {name: name}); - }; - - modes.afterFrameset.endTagHtml = function(name) { - tree.setInsertionMode('afterAfterFrameset'); - }; - - modes.afterFrameset.endTagOther = function(name) { - tree.parseError("unexpected-end-tag-after-frameset", {name: name}); - }; - - modes.beforeHead = Object.create(modes.base); - - modes.beforeHead.start_tag_handlers = { - html: 'startTagHtml', - head: 'startTagHead', - '-default': 'startTagOther' - }; - - modes.beforeHead.end_tag_handlers = { - html: 'endTagImplyHead', - head: 'endTagImplyHead', - body: 'endTagImplyHead', - br: 'endTagImplyHead', - '-default': 'endTagOther' - }; - - modes.beforeHead.processEOF = function() { - this.startTagHead('head', []); - tree.insertionMode.processEOF(); - }; - - modes.beforeHead.processCharacters = function(buffer) { - buffer.skipLeadingWhitespace(); - if (!buffer.length) - return; - this.startTagHead('head', []); - tree.insertionMode.processCharacters(buffer); - }; - - modes.beforeHead.startTagHead = function(name, attributes) { - tree.insertHeadElement(attributes); - tree.setInsertionMode('inHead'); - }; - - modes.beforeHead.startTagOther = function(name, attributes, selfClosing) { - this.startTagHead('head', []); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.beforeHead.endTagImplyHead = function(name) { - this.startTagHead('head', []); - tree.insertionMode.processEndTag(name); - }; - - modes.beforeHead.endTagOther = function(name) { - tree.parseError('end-tag-after-implied-root', {name: name}); - }; - - modes.inHead = Object.create(modes.base); - - modes.inHead.start_tag_handlers = { - html: 'startTagHtml', - head: 'startTagHead', - title: 'startTagTitle', - script: 'startTagScript', - style: 'startTagNoFramesStyle', - noscript: 'startTagNoScript', - noframes: 'startTagNoFramesStyle', - base: 'startTagBaseBasefontBgsoundLink', - basefont: 'startTagBaseBasefontBgsoundLink', - bgsound: 'startTagBaseBasefontBgsoundLink', - link: 'startTagBaseBasefontBgsoundLink', - meta: 'startTagMeta', - "-default": 'startTagOther' - }; - - modes.inHead.end_tag_handlers = { - head: 'endTagHead', - html: 'endTagHtmlBodyBr', - body: 'endTagHtmlBodyBr', - br: 'endTagHtmlBodyBr', - "-default": 'endTagOther' - }; - - modes.inHead.processEOF = function() { - var name = tree.currentStackItem().localName; - if (['title', 'style', 'script'].indexOf(name) != -1) { - tree.parseError("expected-named-closing-tag-but-got-eof", {name: name}); - tree.popElement(); - } - - this.anythingElse(); - - tree.insertionMode.processEOF(); - }; - - modes.inHead.processCharacters = function(buffer) { - var leadingWhitespace = buffer.takeLeadingWhitespace(); - if (leadingWhitespace) - tree.insertText(leadingWhitespace); - if (!buffer.length) - return; - this.anythingElse(); - tree.insertionMode.processCharacters(buffer); - }; - - modes.inHead.startTagHtml = function(name, attributes) { - modes.inBody.processStartTag(name, attributes); - }; - - modes.inHead.startTagHead = function(name, attributes) { - tree.parseError('two-heads-are-not-better-than-one'); - }; - - modes.inHead.startTagTitle = function(name, attributes) { - tree.processGenericRCDATAStartTag(name, attributes); - }; - - modes.inHead.startTagNoScript = function(name, attributes) { - if (tree.scriptingEnabled) - return tree.processGenericRawTextStartTag(name, attributes); - tree.insertElement(name, attributes); - tree.setInsertionMode('inHeadNoscript'); - }; - - modes.inHead.startTagNoFramesStyle = function(name, attributes) { - // XXX Need to decide whether to implement the scripting disabled case - tree.processGenericRawTextStartTag(name, attributes); - }; - - modes.inHead.startTagScript = function(name, attributes) { - tree.insertElement(name, attributes); - tree.tokenizer.setState(Tokenizer.SCRIPT_DATA); - tree.originalInsertionMode = tree.insertionModeName; - tree.setInsertionMode('text'); - }; - - modes.inHead.startTagBaseBasefontBgsoundLink = function(name, attributes) { - tree.insertSelfClosingElement(name, attributes); - }; - - modes.inHead.startTagMeta = function(name, attributes) { - tree.insertSelfClosingElement(name, attributes); - // @todo process charset attributes - }; - - modes.inHead.startTagOther = function(name, attributes, selfClosing) { - this.anythingElse(); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.inHead.endTagHead = function(name) { - if (tree.openElements.item(tree.openElements.length - 1).localName == 'head') { - tree.openElements.pop(); - } else { - tree.parseError('unexpected-end-tag', {name: 'head'}); - } - tree.setInsertionMode('afterHead'); - }; - - modes.inHead.endTagHtmlBodyBr = function(name) { - this.anythingElse(); - tree.insertionMode.processEndTag(name); - }; - - modes.inHead.endTagOther = function(name) { - tree.parseError('unexpected-end-tag', {name: name}); - }; - - modes.inHead.anythingElse = function() { - this.endTagHead('head'); - }; - - modes.afterHead = Object.create(modes.base); - - modes.afterHead.start_tag_handlers = { - html: 'startTagHtml', - head: 'startTagHead', - body: 'startTagBody', - frameset: 'startTagFrameset', - base: 'startTagFromHead', - link: 'startTagFromHead', - meta: 'startTagFromHead', - script: 'startTagFromHead', - // XXX noframes: 'startTagFromHead' ? - style: 'startTagFromHead', - title: 'startTagFromHead', - "-default": 'startTagOther' - }; - - modes.afterHead.end_tag_handlers = { - body: 'endTagBodyHtmlBr', - html: 'endTagBodyHtmlBr', - br: 'endTagBodyHtmlBr', - "-default": 'endTagOther' - }; - - modes.afterHead.processEOF = function() { - this.anythingElse(); - tree.insertionMode.processEOF(); - }; - - modes.afterHead.processCharacters = function(buffer) { - var leadingWhitespace = buffer.takeLeadingWhitespace(); - if (leadingWhitespace) - tree.insertText(leadingWhitespace); - if (!buffer.length) - return; - this.anythingElse(); - tree.insertionMode.processCharacters(buffer); - }; - - modes.afterHead.startTagHtml = function(name, attributes) { - modes.inBody.processStartTag(name, attributes); - }; - - modes.afterHead.startTagBody = function(name, attributes) { - tree.framesetOk = false; - tree.insertBodyElement(attributes); - tree.setInsertionMode('inBody'); - }; - - modes.afterHead.startTagFrameset = function(name, attributes) { - tree.insertElement(name, attributes); - tree.setInsertionMode('inFrameset'); - }; - - modes.afterHead.startTagFromHead = function(name, attributes, selfClosing) { - tree.parseError("unexpected-start-tag-out-of-my-head", {name: name}); - // FIXME head pointer - tree.openElements.push(tree.head); - modes.inHead.processStartTag(name, attributes, selfClosing); - tree.openElements.remove(tree.head); - }; - - modes.afterHead.startTagHead = function(name, attributes, selfClosing) { - tree.parseError('unexpected-start-tag', {name: name}); - }; - - modes.afterHead.startTagOther = function(name, attributes, selfClosing) { - this.anythingElse(); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.afterHead.endTagBodyHtmlBr = function(name) { - this.anythingElse(); - tree.insertionMode.processEndTag(name); - }; - - modes.afterHead.endTagOther = function(name) { - tree.parseError('unexpected-end-tag', {name: name}); - }; - - modes.afterHead.anythingElse = function() { - tree.insertBodyElement([]); - tree.setInsertionMode('inBody'); - tree.framesetOk = true; - } - - modes.inBody = Object.create(modes.base); - - modes.inBody.start_tag_handlers = { - html: 'startTagHtml', - head: 'startTagMisplaced', - base: 'startTagProcessInHead', - basefont: 'startTagProcessInHead', - bgsound: 'startTagProcessInHead', - link: 'startTagProcessInHead', - meta: 'startTagProcessInHead', - noframes: 'startTagProcessInHead', - script: 'startTagProcessInHead', - style: 'startTagProcessInHead', - title: 'startTagProcessInHead', - body: 'startTagBody', - form: 'startTagForm', - plaintext: 'startTagPlaintext', - a: 'startTagA', - button: 'startTagButton', - xmp: 'startTagXmp', - table: 'startTagTable', - hr: 'startTagHr', - image: 'startTagImage', - input: 'startTagInput', - textarea: 'startTagTextarea', - select: 'startTagSelect', - isindex: 'startTagIsindex', - applet: 'startTagAppletMarqueeObject', - marquee: 'startTagAppletMarqueeObject', - object: 'startTagAppletMarqueeObject', - li: 'startTagListItem', - dd: 'startTagListItem', - dt: 'startTagListItem', - address: 'startTagCloseP', - article: 'startTagCloseP', - aside: 'startTagCloseP', - blockquote: 'startTagCloseP', - center: 'startTagCloseP', - details: 'startTagCloseP', - dir: 'startTagCloseP', - div: 'startTagCloseP', - dl: 'startTagCloseP', - fieldset: 'startTagCloseP', - figcaption: 'startTagCloseP', - figure: 'startTagCloseP', - footer: 'startTagCloseP', - header: 'startTagCloseP', - hgroup: 'startTagCloseP', - main: 'startTagCloseP', - menu: 'startTagCloseP', - nav: 'startTagCloseP', - ol: 'startTagCloseP', - p: 'startTagCloseP', - section: 'startTagCloseP', - summary: 'startTagCloseP', - ul: 'startTagCloseP', - listing: 'startTagPreListing', - pre: 'startTagPreListing', - b: 'startTagFormatting', - big: 'startTagFormatting', - code: 'startTagFormatting', - em: 'startTagFormatting', - font: 'startTagFormatting', - i: 'startTagFormatting', - s: 'startTagFormatting', - small: 'startTagFormatting', - strike: 'startTagFormatting', - strong: 'startTagFormatting', - tt: 'startTagFormatting', - u: 'startTagFormatting', - nobr: 'startTagNobr', - area: 'startTagVoidFormatting', - br: 'startTagVoidFormatting', - embed: 'startTagVoidFormatting', - img: 'startTagVoidFormatting', - keygen: 'startTagVoidFormatting', - wbr: 'startTagVoidFormatting', - param: 'startTagParamSourceTrack', - source: 'startTagParamSourceTrack', - track: 'startTagParamSourceTrack', - iframe: 'startTagIFrame', - noembed: 'startTagRawText', - noscript: 'startTagRawText', - h1: 'startTagHeading', - h2: 'startTagHeading', - h3: 'startTagHeading', - h4: 'startTagHeading', - h5: 'startTagHeading', - h6: 'startTagHeading', - caption: 'startTagMisplaced', - col: 'startTagMisplaced', - colgroup: 'startTagMisplaced', - frame: 'startTagMisplaced', - frameset: 'startTagFrameset', - tbody: 'startTagMisplaced', - td: 'startTagMisplaced', - tfoot: 'startTagMisplaced', - th: 'startTagMisplaced', - thead: 'startTagMisplaced', - tr: 'startTagMisplaced', - option: 'startTagOptionOptgroup', - optgroup: 'startTagOptionOptgroup', - math: 'startTagMath', - svg: 'startTagSVG', - rt: 'startTagRpRt', - rp: 'startTagRpRt', - "-default": 'startTagOther' - }; - - modes.inBody.end_tag_handlers = { - p: 'endTagP', - body: 'endTagBody', - html: 'endTagHtml', - address: 'endTagBlock', - article: 'endTagBlock', - aside: 'endTagBlock', - blockquote: 'endTagBlock', - button: 'endTagBlock', - center: 'endTagBlock', - details: 'endTagBlock', - dir: 'endTagBlock', - div: 'endTagBlock', - dl: 'endTagBlock', - fieldset: 'endTagBlock', - figcaption: 'endTagBlock', - figure: 'endTagBlock', - footer: 'endTagBlock', - header: 'endTagBlock', - hgroup: 'endTagBlock', - listing: 'endTagBlock', - main: 'endTagBlock', - menu: 'endTagBlock', - nav: 'endTagBlock', - ol: 'endTagBlock', - pre: 'endTagBlock', - section: 'endTagBlock', - summary: 'endTagBlock', - ul: 'endTagBlock', - form: 'endTagForm', - applet: 'endTagAppletMarqueeObject', - marquee: 'endTagAppletMarqueeObject', - object: 'endTagAppletMarqueeObject', - dd: 'endTagListItem', - dt: 'endTagListItem', - li: 'endTagListItem', - h1: 'endTagHeading', - h2: 'endTagHeading', - h3: 'endTagHeading', - h4: 'endTagHeading', - h5: 'endTagHeading', - h6: 'endTagHeading', - a: 'endTagFormatting', - b: 'endTagFormatting', - big: 'endTagFormatting', - code: 'endTagFormatting', - em: 'endTagFormatting', - font: 'endTagFormatting', - i: 'endTagFormatting', - nobr: 'endTagFormatting', - s: 'endTagFormatting', - small: 'endTagFormatting', - strike: 'endTagFormatting', - strong: 'endTagFormatting', - tt: 'endTagFormatting', - u: 'endTagFormatting', - br: 'endTagBr', - "-default": 'endTagOther' - }; - - modes.inBody.processCharacters = function(buffer) { - if (tree.shouldSkipLeadingNewline) { - tree.shouldSkipLeadingNewline = false; - buffer.skipAtMostOneLeadingNewline(); - } - tree.reconstructActiveFormattingElements(); - var characters = buffer.takeRemaining(); - characters = characters.replace(/\u0000/g, function(match, index){ - // @todo position - tree.parseError("invalid-codepoint"); - return ''; - }); - if (!characters) - return; - tree.insertText(characters); - if (tree.framesetOk && !isAllWhitespaceOrReplacementCharacters(characters)) - tree.framesetOk = false; - }; - - modes.inBody.startTagHtml = function(name, attributes) { - tree.parseError('non-html-root'); - tree.addAttributesToElement(tree.openElements.rootNode, attributes); - }; - - modes.inBody.startTagProcessInHead = function(name, attributes) { - modes.inHead.processStartTag(name, attributes); - }; - - modes.inBody.startTagBody = function(name, attributes) { - tree.parseError('unexpected-start-tag', {name: 'body'}); - if (tree.openElements.length == 1 || - tree.openElements.item(1).localName != 'body') { - assert.ok(tree.context); - } else { - tree.framesetOk = false; - tree.addAttributesToElement(tree.openElements.bodyElement, attributes); - } - }; - - modes.inBody.startTagFrameset = function(name, attributes) { - tree.parseError('unexpected-start-tag', {name: 'frameset'}); - if (tree.openElements.length == 1 || - tree.openElements.item(1).localName != 'body') { - assert.ok(tree.context); - } else if (tree.framesetOk) { - tree.detachFromParent(tree.openElements.bodyElement); - while (tree.openElements.length > 1) - tree.openElements.pop(); - tree.insertElement(name, attributes); - tree.setInsertionMode('inFrameset'); - } - }; - - modes.inBody.startTagCloseP = function(name, attributes) { - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - tree.insertElement(name, attributes); - }; - - modes.inBody.startTagPreListing = function(name, attributes) { - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - tree.insertElement(name, attributes); - tree.framesetOk = false; - tree.shouldSkipLeadingNewline = true; - }; - - modes.inBody.startTagForm = function(name, attributes) { - if (tree.form) { - tree.parseError('unexpected-start-tag', {name: name}); - } else { - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - tree.insertElement(name, attributes); - tree.form = tree.currentStackItem(); - } - }; - - modes.inBody.startTagRpRt = function(name, attributes) { - if (tree.openElements.inScope('ruby')) { - tree.generateImpliedEndTags(); - if (tree.currentStackItem().localName != 'ruby') { - tree.parseError('unexpected-start-tag', {name: name}); - } - } - tree.insertElement(name, attributes); - }; - - modes.inBody.startTagListItem = function(name, attributes) { - /// @todo: Fix according to current spec. http://www.w3.org/TR/html5/tree-construction.html#parsing-main-inbody - var stopNames = {li: ['li'], dd: ['dd', 'dt'], dt: ['dd', 'dt']}; - var stopName = stopNames[name]; - - var els = tree.openElements; - for (var i = els.length - 1; i >= 0; i--) { - var node = els.item(i); - if (stopName.indexOf(node.localName) != -1) { - tree.insertionMode.processEndTag(node.localName); - break; - } - - // todo isScoping() - if (node.isSpecial() && node.localName !== 'p' && node.localName !== 'address' && node.localName !== 'div') - break; - } - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - - // Always insert an
  • element - tree.insertElement(name, attributes); - tree.framesetOk = false; - }; - - modes.inBody.startTagPlaintext = function(name, attributes) { - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - tree.insertElement(name, attributes); - tree.tokenizer.setState(Tokenizer.PLAINTEXT); - }; - - modes.inBody.startTagHeading = function(name, attributes) { - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - if (tree.currentStackItem().isNumberedHeader()) { - tree.parseError('unexpected-start-tag', {name: name}); - tree.popElement(); - } - tree.insertElement(name, attributes); - }; - - modes.inBody.startTagA = function(name, attributes) { - var activeA = tree.elementInActiveFormattingElements('a'); - if (activeA) { - tree.parseError("unexpected-start-tag-implies-end-tag", {startName: "a", endName: "a"}); - tree.adoptionAgencyEndTag('a'); - if (tree.openElements.contains(activeA)) - tree.openElements.remove(activeA); - tree.removeElementFromActiveFormattingElements(activeA); - } - tree.reconstructActiveFormattingElements(); - tree.insertFormattingElement(name, attributes); - }; - - modes.inBody.startTagFormatting = function(name, attributes) { - tree.reconstructActiveFormattingElements(); - tree.insertFormattingElement(name, attributes); - }; - - modes.inBody.startTagNobr = function(name, attributes) { - tree.reconstructActiveFormattingElements(); - if (tree.openElements.inScope('nobr')) { - tree.parseError("unexpected-start-tag-implies-end-tag", {startName: 'nobr', endName: 'nobr'}); - this.processEndTag('nobr'); - // XXX Need tests that trigger the following - tree.reconstructActiveFormattingElements(); - } - tree.insertFormattingElement(name, attributes); - }; - - modes.inBody.startTagButton = function(name, attributes) { - if (tree.openElements.inScope('button')) { - tree.parseError('unexpected-start-tag-implies-end-tag', {startName: 'button', endName: 'button'}); - this.processEndTag('button'); - tree.insertionMode.processStartTag(name, attributes); - } else { - tree.framesetOk = false; - tree.reconstructActiveFormattingElements(); - tree.insertElement(name, attributes); - } - }; - - modes.inBody.startTagAppletMarqueeObject = function(name, attributes) { - tree.reconstructActiveFormattingElements(); - tree.insertElement(name, attributes); - tree.activeFormattingElements.push(Marker); - tree.framesetOk = false; - }; - - modes.inBody.endTagAppletMarqueeObject = function(name) { - if (!tree.openElements.inScope(name)) { - tree.parseError("unexpected-end-tag", {name: name}); - } else { - tree.generateImpliedEndTags(); - if (tree.currentStackItem().localName != name) { - tree.parseError('end-tag-too-early', {name: name}); - } - tree.openElements.popUntilPopped(name); - tree.clearActiveFormattingElements(); - } - }; - - modes.inBody.startTagXmp = function(name, attributes) { - if (tree.openElements.inButtonScope('p')) - this.processEndTag('p'); - tree.reconstructActiveFormattingElements(); - tree.processGenericRawTextStartTag(name, attributes); - tree.framesetOk = false; - }; - - modes.inBody.startTagTable = function(name, attributes) { - if (tree.compatMode !== "quirks") - if (tree.openElements.inButtonScope('p')) - this.processEndTag('p'); - tree.insertElement(name, attributes); - tree.setInsertionMode('inTable'); - tree.framesetOk = false; - }; - - modes.inBody.startTagVoidFormatting = function(name, attributes) { - tree.reconstructActiveFormattingElements(); - tree.insertSelfClosingElement(name, attributes); - tree.framesetOk = false; - }; - - modes.inBody.startTagParamSourceTrack = function(name, attributes) { - tree.insertSelfClosingElement(name, attributes); - }; - - modes.inBody.startTagHr = function(name, attributes) { - if (tree.openElements.inButtonScope('p')) - this.endTagP('p'); - tree.insertSelfClosingElement(name, attributes); - tree.framesetOk = false; - }; - - modes.inBody.startTagImage = function(name, attributes) { - // No, really... - tree.parseError('unexpected-start-tag-treated-as', {originalName: 'image', newName: 'img'}); - this.processStartTag('img', attributes); - }; - - modes.inBody.startTagInput = function(name, attributes) { - var currentFramesetOk = tree.framesetOk; - this.startTagVoidFormatting(name, attributes); - for (var key in attributes) { - // input type=hidden doesn't change framesetOk - if (attributes[key].nodeName == 'type') { - if (attributes[key].nodeValue.toLowerCase() == 'hidden') - tree.framesetOk = currentFramesetOk; - break; - } - } - }; - - modes.inBody.startTagIsindex = function(name, attributes) { - tree.parseError('deprecated-tag', {name: 'isindex'}); - tree.selfClosingFlagAcknowledged = true; - if (tree.form) - return; - var formAttributes = []; - var inputAttributes = []; - var prompt = "This is a searchable index. Enter search keywords: "; - for (var key in attributes) { - switch (attributes[key].nodeName) { - case 'action': - formAttributes.push({nodeName: 'action', - nodeValue: attributes[key].nodeValue}); - break; - case 'prompt': - prompt = attributes[key].nodeValue; - break; - case 'name': - break; - default: - inputAttributes.push({nodeName: attributes[key].nodeName, - nodeValue: attributes[key].nodeValue}); - } - } - inputAttributes.push({nodeName: 'name', nodeValue: 'isindex'}); - this.processStartTag('form', formAttributes); - this.processStartTag('hr'); - this.processStartTag('label'); - this.processCharacters(new CharacterBuffer(prompt)); - this.processStartTag('input', inputAttributes); - this.processEndTag('label'); - this.processStartTag('hr'); - this.processEndTag('form'); - }; - - modes.inBody.startTagTextarea = function(name, attributes) { - // XXX Form element pointer checking here as well... - tree.insertElement(name, attributes); - tree.tokenizer.setState(Tokenizer.RCDATA); - tree.originalInsertionMode = tree.insertionModeName; - tree.shouldSkipLeadingNewline = true; - tree.framesetOk = false; - tree.setInsertionMode('text'); - }; - - modes.inBody.startTagIFrame = function(name, attributes) { - tree.framesetOk = false; - this.startTagRawText(name, attributes); - }; - - modes.inBody.startTagRawText = function(name, attributes) { - tree.processGenericRawTextStartTag(name, attributes); - }; - - modes.inBody.startTagSelect = function(name, attributes) { - tree.reconstructActiveFormattingElements(); - tree.insertElement(name, attributes); - tree.framesetOk = false; - var insertionModeName = tree.insertionModeName; - if (insertionModeName == 'inTable' || - insertionModeName == 'inCaption' || - insertionModeName == 'inColumnGroup' || - insertionModeName == 'inTableBody' || - insertionModeName == 'inRow' || - insertionModeName == 'inCell') { - tree.setInsertionMode('inSelectInTable'); - } else { - tree.setInsertionMode('inSelect'); - } - }; - - modes.inBody.startTagMisplaced = function(name, attributes) { - tree.parseError('unexpected-start-tag-ignored', {name: name}); - }; - - modes.inBody.endTagMisplaced = function(name) { - // This handles elements with end tags in other insertion modes. - tree.parseError("unexpected-end-tag", {name: name}); - }; - - modes.inBody.endTagBr = function(name) { - tree.parseError("unexpected-end-tag-treated-as", {originalName: "br", newName: "br element"}); - tree.reconstructActiveFormattingElements(); - tree.insertElement(name, []); - tree.popElement(); - }; - - modes.inBody.startTagOptionOptgroup = function(name, attributes) { - if (tree.currentStackItem().localName == 'option') - tree.popElement(); - tree.reconstructActiveFormattingElements(); - tree.insertElement(name, attributes); - }; - - modes.inBody.startTagOther = function(name, attributes) { - tree.reconstructActiveFormattingElements(); - tree.insertElement(name, attributes); - }; - - modes.inBody.endTagOther = function(name) { - var node; - for (var i = tree.openElements.length - 1; i > 0; i--) { - node = tree.openElements.item(i); - if (node.localName == name) { - tree.generateImpliedEndTags(name); - if (tree.currentStackItem().localName != name) - tree.parseError('unexpected-end-tag', {name: name}); - // todo optimize - tree.openElements.remove_openElements_until(function(x) {return x === node;}); - break; - } - if (node.isSpecial()) { - tree.parseError('unexpected-end-tag', {name: name}); - break; - } - } - }; - - modes.inBody.startTagMath = function(name, attributes, selfClosing) { - tree.reconstructActiveFormattingElements(); - attributes = tree.adjustMathMLAttributes(attributes); - attributes = tree.adjustForeignAttributes(attributes); - tree.insertForeignElement(name, attributes, "http://www.w3.org/1998/Math/MathML", selfClosing); - // Need to get the parse error right for the case where the token - // has a namespace not equal to the xmlns attribute - }; - - modes.inBody.startTagSVG = function(name, attributes, selfClosing) { - tree.reconstructActiveFormattingElements(); - attributes = tree.adjustSVGAttributes(attributes); - attributes = tree.adjustForeignAttributes(attributes); - tree.insertForeignElement(name, attributes, "http://www.w3.org/2000/svg", selfClosing); - // Need to get the parse error right for the case where the token - // has a namespace not equal to the xmlns attribute - }; - - modes.inBody.endTagP = function(name) { - if (!tree.openElements.inButtonScope('p')) { - tree.parseError('unexpected-end-tag', {name: 'p'}); - this.startTagCloseP('p', []); - this.endTagP('p'); - } else { - tree.generateImpliedEndTags('p'); - if (tree.currentStackItem().localName != 'p') - tree.parseError('unexpected-implied-end-tag', {name: 'p'}); - tree.openElements.popUntilPopped(name); - } - }; - - modes.inBody.endTagBody = function(name) { - if (!tree.openElements.inScope('body')) { - tree.parseError('unexpected-end-tag', {name: name}); - return; - } - - /// @todo Emit parse error on end tags other than the ones listed in http://www.w3.org/TR/html5/tree-construction.html#parsing-main-inbody - // ['dd', 'dt', 'li', 'optgroup', 'option', 'p', 'rp', 'rt', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'body', 'html'] - if (tree.currentStackItem().localName != 'body') { - tree.parseError('expected-one-end-tag-but-got-another', { - expectedName: tree.currentStackItem().localName, - gotName: name - }); - } - tree.setInsertionMode('afterBody'); - }; - - modes.inBody.endTagHtml = function(name) { - if (!tree.openElements.inScope('body')) { - tree.parseError('unexpected-end-tag', {name: name}); - return; - } - - /// @todo Emit parse error on end tags other than the ones listed in http://www.w3.org/TR/html5/tree-construction.html#parsing-main-inbody - // ['dd', 'dt', 'li', 'optgroup', 'option', 'p', 'rp', 'rt', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', 'body', 'html'] - if (tree.currentStackItem().localName != 'body') { - tree.parseError('expected-one-end-tag-but-got-another', { - expectedName: tree.currentStackItem().localName, - gotName: name - }); - } - tree.setInsertionMode('afterBody'); - tree.insertionMode.processEndTag(name); - }; - - modes.inBody.endTagBlock = function(name) { - if (!tree.openElements.inScope(name)) { - tree.parseError('unexpected-end-tag', {name: name}); - } else { - tree.generateImpliedEndTags(); - if (tree.currentStackItem().localName != name) { - tree.parseError('end-tag-too-early', {name: name}); - } - tree.openElements.popUntilPopped(name); - } - }; - - modes.inBody.endTagForm = function(name) { - var node = tree.form; - tree.form = null; - if (!node || !tree.openElements.inScope(name)) { - tree.parseError('unexpected-end-tag', {name: name}); - } else { - tree.generateImpliedEndTags(); - if (tree.currentStackItem() != node) { - tree.parseError('end-tag-too-early-ignored', {name: 'form'}); - } - tree.openElements.remove(node); - } - }; - - modes.inBody.endTagListItem = function(name) { - if (!tree.openElements.inListItemScope(name)) { - tree.parseError('unexpected-end-tag', {name: name}); - } else { - tree.generateImpliedEndTags(name); - if (tree.currentStackItem().localName != name) - tree.parseError('end-tag-too-early', {name: name}); - tree.openElements.popUntilPopped(name); - } - }; - - modes.inBody.endTagHeading = function(name) { - if (!tree.openElements.hasNumberedHeaderElementInScope()) { - tree.parseError('unexpected-end-tag', {name: name}); - return; - } - tree.generateImpliedEndTags(); - if (tree.currentStackItem().localName != name) - tree.parseError('end-tag-too-early', {name: name}); - - tree.openElements.remove_openElements_until(function(e) { - return e.isNumberedHeader(); - }); - }; - - modes.inBody.endTagFormatting = function(name, attributes) { - if (!tree.adoptionAgencyEndTag(name)) - this.endTagOther(name, attributes); - }; - - modes.inCaption = Object.create(modes.base); - - modes.inCaption.start_tag_handlers = { - html: 'startTagHtml', - caption: 'startTagTableElement', - col: 'startTagTableElement', - colgroup: 'startTagTableElement', - tbody: 'startTagTableElement', - td: 'startTagTableElement', - tfoot: 'startTagTableElement', - thead: 'startTagTableElement', - tr: 'startTagTableElement', - '-default': 'startTagOther' - }; - - modes.inCaption.end_tag_handlers = { - caption: 'endTagCaption', - table: 'endTagTable', - body: 'endTagIgnore', - col: 'endTagIgnore', - colgroup: 'endTagIgnore', - html: 'endTagIgnore', - tbody: 'endTagIgnore', - td: 'endTagIgnore', - tfood: 'endTagIgnore', - thead: 'endTagIgnore', - tr: 'endTagIgnore', - '-default': 'endTagOther' - }; - - modes.inCaption.processCharacters = function(data) { - modes.inBody.processCharacters(data); - }; - - modes.inCaption.startTagTableElement = function(name, attributes) { - tree.parseError('unexpected-end-tag', {name: name}); - var ignoreEndTag = !tree.openElements.inTableScope('caption'); - tree.insertionMode.processEndTag('caption'); - if (!ignoreEndTag) tree.insertionMode.processStartTag(name, attributes); - }; - - modes.inCaption.startTagOther = function(name, attributes, selfClosing) { - modes.inBody.processStartTag(name, attributes, selfClosing); - }; - - modes.inCaption.endTagCaption = function(name) { - if (!tree.openElements.inTableScope('caption')) { - // context case - assert.ok(tree.context); - tree.parseError('unexpected-end-tag', {name: name}); - } else { - // AT this code is quite similar to endTagTable in inTable - tree.generateImpliedEndTags(); - if (tree.currentStackItem().localName != 'caption') { - // @todo this is confusing for implied end tag - tree.parseError('expected-one-end-tag-but-got-another', { - gotName: "caption", - expectedName: tree.currentStackItem().localName - }); - } - tree.openElements.popUntilPopped('caption'); - tree.clearActiveFormattingElements(); - tree.setInsertionMode('inTable'); - } - }; - - modes.inCaption.endTagTable = function(name) { - tree.parseError("unexpected-end-table-in-caption"); - var ignoreEndTag = !tree.openElements.inTableScope('caption'); - tree.insertionMode.processEndTag('caption'); - if (!ignoreEndTag) tree.insertionMode.processEndTag(name); - }; - - modes.inCaption.endTagIgnore = function(name) { - tree.parseError('unexpected-end-tag', {name: name}); - }; - - modes.inCaption.endTagOther = function(name) { - modes.inBody.processEndTag(name); - }; - - modes.inCell = Object.create(modes.base); - - modes.inCell.start_tag_handlers = { - html: 'startTagHtml', - caption: 'startTagTableOther', - col: 'startTagTableOther', - colgroup: 'startTagTableOther', - tbody: 'startTagTableOther', - td: 'startTagTableOther', - tfoot: 'startTagTableOther', - th: 'startTagTableOther', - thead: 'startTagTableOther', - tr: 'startTagTableOther', - '-default': 'startTagOther' - }; - - modes.inCell.end_tag_handlers = { - td: 'endTagTableCell', - th: 'endTagTableCell', - body: 'endTagIgnore', - caption: 'endTagIgnore', - col: 'endTagIgnore', - colgroup: 'endTagIgnore', - html: 'endTagIgnore', - table: 'endTagImply', - tbody: 'endTagImply', - tfoot: 'endTagImply', - thead: 'endTagImply', - tr: 'endTagImply', - '-default': 'endTagOther' - }; - - modes.inCell.processCharacters = function(data) { - modes.inBody.processCharacters(data); - }; - - modes.inCell.startTagTableOther = function(name, attributes, selfClosing) { - if (tree.openElements.inTableScope('td') || tree.openElements.inTableScope('th')) { - this.closeCell(); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - } else { - // context case - tree.parseError('unexpected-start-tag', {name: name}); - } - }; - - modes.inCell.startTagOther = function(name, attributes, selfClosing) { - modes.inBody.processStartTag(name, attributes, selfClosing); - }; - - modes.inCell.endTagTableCell = function(name) { - if (tree.openElements.inTableScope(name)) { - tree.generateImpliedEndTags(name); - if (tree.currentStackItem().localName != name.toLowerCase()) { - tree.parseError('unexpected-cell-end-tag', {name: name}); - tree.openElements.popUntilPopped(name); - } else { - tree.popElement(); - } - tree.clearActiveFormattingElements(); - tree.setInsertionMode('inRow'); - } else { - tree.parseError('unexpected-end-tag', {name: name}); - } - }; - - modes.inCell.endTagIgnore = function(name) { - tree.parseError('unexpected-end-tag', {name: name}); - }; - - modes.inCell.endTagImply = function(name) { - if (tree.openElements.inTableScope(name)) { - this.closeCell(); - tree.insertionMode.processEndTag(name); - } else { - // sometimes context case - tree.parseError('unexpected-end-tag', {name: name}); - } - }; - - modes.inCell.endTagOther = function(name) { - modes.inBody.processEndTag(name); - }; - - modes.inCell.closeCell = function() { - if (tree.openElements.inTableScope('td')) { - this.endTagTableCell('td'); - } else if (tree.openElements.inTableScope('th')) { - this.endTagTableCell('th'); - } - }; - - - modes.inColumnGroup = Object.create(modes.base); - - modes.inColumnGroup.start_tag_handlers = { - html: 'startTagHtml', - col: 'startTagCol', - '-default': 'startTagOther' - }; - - modes.inColumnGroup.end_tag_handlers = { - colgroup: 'endTagColgroup', - col: 'endTagCol', - '-default': 'endTagOther' - }; - - modes.inColumnGroup.ignoreEndTagColgroup = function() { - return tree.currentStackItem().localName == 'html'; - }; - - modes.inColumnGroup.processCharacters = function(buffer) { - var leadingWhitespace = buffer.takeLeadingWhitespace(); - if (leadingWhitespace) - tree.insertText(leadingWhitespace); - if (!buffer.length) - return; - var ignoreEndTag = this.ignoreEndTagColgroup(); - this.endTagColgroup('colgroup'); - if (!ignoreEndTag) tree.insertionMode.processCharacters(buffer); - }; - - modes.inColumnGroup.startTagCol = function(name, attributes) { - tree.insertSelfClosingElement(name, attributes); - }; - - modes.inColumnGroup.startTagOther = function(name, attributes, selfClosing) { - var ignoreEndTag = this.ignoreEndTagColgroup(); - this.endTagColgroup('colgroup'); - if (!ignoreEndTag) tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.inColumnGroup.endTagColgroup = function(name) { - if (this.ignoreEndTagColgroup()) { - // context case - assert.ok(tree.context); - tree.parseError('unexpected-end-tag', {name: name}); - } else { - tree.popElement(); - tree.setInsertionMode('inTable'); - } - }; - - modes.inColumnGroup.endTagCol = function(name) { - tree.parseError("no-end-tag", {name: 'col'}); - }; - - modes.inColumnGroup.endTagOther = function(name) { - var ignoreEndTag = this.ignoreEndTagColgroup(); - this.endTagColgroup('colgroup'); - if (!ignoreEndTag) tree.insertionMode.processEndTag(name) ; - }; - - modes.inForeignContent = Object.create(modes.base); - - modes.inForeignContent.processStartTag = function(name, attributes, selfClosing) { - if (['b', 'big', 'blockquote', 'body', 'br', 'center', 'code', 'dd', 'div', 'dl', 'dt', 'em', 'embed', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'i', 'img', 'li', 'listing', 'menu', 'meta', 'nobr', 'ol', 'p', 'pre', 'ruby', 's', 'small', 'span', 'strong', 'strike', 'sub', 'sup', 'table', 'tt', 'u', 'ul', 'var'].indexOf(name) != -1 - || (name == 'font' && attributes.some(function(attr){ return ['color', 'face', 'size'].indexOf(attr.nodeName) >= 0 }))) { - tree.parseError('unexpected-html-element-in-foreign-content', {name: name}); - while (tree.currentStackItem().isForeign() - && !tree.currentStackItem().isHtmlIntegrationPoint() - && !tree.currentStackItem().isMathMLTextIntegrationPoint()) { - tree.openElements.pop(); - } - tree.insertionMode.processStartTag(name, attributes, selfClosing); - return; - } - if (tree.currentStackItem().namespaceURI == "http://www.w3.org/1998/Math/MathML") { - attributes = tree.adjustMathMLAttributes(attributes); - } - if (tree.currentStackItem().namespaceURI == "http://www.w3.org/2000/svg") { - name = tree.adjustSVGTagNameCase(name); - attributes = tree.adjustSVGAttributes(attributes); - } - attributes = tree.adjustForeignAttributes(attributes); - tree.insertForeignElement(name, attributes, tree.currentStackItem().namespaceURI, selfClosing); - }; - - modes.inForeignContent.processEndTag = function(name) { - var node = tree.currentStackItem(); - var index = tree.openElements.length - 1; - if (node.localName.toLowerCase() != name) - tree.parseError("unexpected-end-tag", {name: name}); - - while (true) { - if (index === 0) - break; - if (node.localName.toLowerCase() == name) { - while (tree.openElements.pop() != node); - break; - } - index -= 1; - node = tree.openElements.item(index); - if (node.isForeign()) { - continue; - } else { - tree.insertionMode.processEndTag(name); - break; - } - } - }; - - modes.inForeignContent.processCharacters = function(buffer) { - var characters = buffer.takeRemaining(); - characters = characters.replace(/\u0000/g, function(match, index){ - // @todo position - tree.parseError('invalid-codepoint'); - return '\uFFFD'; - }); - if (tree.framesetOk && !isAllWhitespaceOrReplacementCharacters(characters)) - tree.framesetOk = false; - tree.insertText(characters); - }; - - modes.inHeadNoscript = Object.create(modes.base); - - modes.inHeadNoscript.start_tag_handlers = { - html: 'startTagHtml', - basefont: 'startTagBasefontBgsoundLinkMetaNoframesStyle', - bgsound: 'startTagBasefontBgsoundLinkMetaNoframesStyle', - link: 'startTagBasefontBgsoundLinkMetaNoframesStyle', - meta: 'startTagBasefontBgsoundLinkMetaNoframesStyle', - noframes: 'startTagBasefontBgsoundLinkMetaNoframesStyle', - style: 'startTagBasefontBgsoundLinkMetaNoframesStyle', - head: 'startTagHeadNoscript', - noscript: 'startTagHeadNoscript', - "-default": 'startTagOther' - }; - - modes.inHeadNoscript.end_tag_handlers = { - noscript: 'endTagNoscript', - br: 'endTagBr', - '-default': 'endTagOther' - }; - - modes.inHeadNoscript.processCharacters = function(buffer) { - var leadingWhitespace = buffer.takeLeadingWhitespace(); - if (leadingWhitespace) - tree.insertText(leadingWhitespace); - if (!buffer.length) - return; - // FIXME error message - tree.parseError("unexpected-char-in-frameset"); - this.anythingElse(); - tree.insertionMode.processCharacters(buffer); - }; - - modes.inHeadNoscript.processComment = function(data) { - modes.inHead.processComment(data); - }; - - modes.inHeadNoscript.startTagBasefontBgsoundLinkMetaNoframesStyle = function(name, attributes) { - modes.inHead.processStartTag(name, attributes); - }; - - modes.inHeadNoscript.startTagHeadNoscript = function(name, attributes) { - // FIXME error message - tree.parseError("unexpected-start-tag-in-frameset", {name: name}); - }; - - modes.inHeadNoscript.startTagOther = function(name, attributes) { - // FIXME error message - tree.parseError("unexpected-start-tag-in-frameset", {name: name}); - this.anythingElse(); - tree.insertionMode.processStartTag(name, attributes); - }; - - modes.inHeadNoscript.endTagBr = function(name, attributes) { - // FIXME error message - tree.parseError("unexpected-end-tag-in-frameset", {name: name}); - this.anythingElse(); - tree.insertionMode.processEndTag(name, attributes); - }; - - modes.inHeadNoscript.endTagNoscript = function(name, attributes) { - tree.popElement(); - tree.setInsertionMode('inHead'); - }; - - modes.inHeadNoscript.endTagOther = function(name, attributes) { - // FIXME error message - tree.parseError("unexpected-end-tag-in-frameset", {name: name}); - }; - - modes.inHeadNoscript.anythingElse = function() { - tree.popElement(); - tree.setInsertionMode('inHead'); - }; - - - modes.inFrameset = Object.create(modes.base); - - modes.inFrameset.start_tag_handlers = { - html: 'startTagHtml', - frameset: 'startTagFrameset', - frame: 'startTagFrame', - noframes: 'startTagNoframes', - "-default": 'startTagOther' - }; - - modes.inFrameset.end_tag_handlers = { - frameset: 'endTagFrameset', - noframes: 'endTagNoframes', - '-default': 'endTagOther' - }; - - modes.inFrameset.processCharacters = function(data) { - tree.parseError("unexpected-char-in-frameset"); - }; - - modes.inFrameset.startTagFrameset = function(name, attributes) { - tree.insertElement(name, attributes); - }; - - modes.inFrameset.startTagFrame = function(name, attributes) { - tree.insertSelfClosingElement(name, attributes); - }; - - modes.inFrameset.startTagNoframes = function(name, attributes) { - modes.inBody.processStartTag(name, attributes); - }; - - modes.inFrameset.startTagOther = function(name, attributes) { - tree.parseError("unexpected-start-tag-in-frameset", {name: name}); - }; - - modes.inFrameset.endTagFrameset = function(name, attributes) { - if (tree.currentStackItem().localName == 'html') { - // context case - tree.parseError("unexpected-frameset-in-frameset-innerhtml"); - } else { - tree.popElement(); - } - - if (!tree.context && tree.currentStackItem().localName != 'frameset') { - // If we're not in context mode an the current node is not a "frameset" element (anymore) then switch - tree.setInsertionMode('afterFrameset'); - } - }; - - modes.inFrameset.endTagNoframes = function(name) { - modes.inBody.processEndTag(name); - }; - - modes.inFrameset.endTagOther = function(name) { - tree.parseError("unexpected-end-tag-in-frameset", {name: name}); - }; - - modes.inTable = Object.create(modes.base); - - modes.inTable.start_tag_handlers = { - html: 'startTagHtml', - caption: 'startTagCaption', - colgroup: 'startTagColgroup', - col: 'startTagCol', - table: 'startTagTable', - tbody: 'startTagRowGroup', - tfoot: 'startTagRowGroup', - thead: 'startTagRowGroup', - td: 'startTagImplyTbody', - th: 'startTagImplyTbody', - tr: 'startTagImplyTbody', - style: 'startTagStyleScript', - script: 'startTagStyleScript', - input: 'startTagInput', - form: 'startTagForm', - '-default': 'startTagOther' - }; - - modes.inTable.end_tag_handlers = { - table: 'endTagTable', - body: 'endTagIgnore', - caption: 'endTagIgnore', - col: 'endTagIgnore', - colgroup: 'endTagIgnore', - html: 'endTagIgnore', - tbody: 'endTagIgnore', - td: 'endTagIgnore', - tfoot: 'endTagIgnore', - th: 'endTagIgnore', - thead: 'endTagIgnore', - tr: 'endTagIgnore', - '-default': 'endTagOther' - }; - - modes.inTable.processCharacters = function(data) { - if (tree.currentStackItem().isFosterParenting()) { - var originalInsertionMode = tree.insertionModeName; - tree.setInsertionMode('inTableText'); - tree.originalInsertionMode = originalInsertionMode; - tree.insertionMode.processCharacters(data); - } else { - tree.redirectAttachToFosterParent = true; - modes.inBody.processCharacters(data); - tree.redirectAttachToFosterParent = false; - } - }; - - modes.inTable.startTagCaption = function(name, attributes) { - tree.openElements.popUntilTableScopeMarker(); - tree.activeFormattingElements.push(Marker); - tree.insertElement(name, attributes); - tree.setInsertionMode('inCaption'); - }; - - modes.inTable.startTagColgroup = function(name, attributes) { - tree.openElements.popUntilTableScopeMarker(); - tree.insertElement(name, attributes); - tree.setInsertionMode('inColumnGroup'); - }; - - modes.inTable.startTagCol = function(name, attributes) { - this.startTagColgroup('colgroup', []); - tree.insertionMode.processStartTag(name, attributes); - }; - - modes.inTable.startTagRowGroup = function(name, attributes) { - tree.openElements.popUntilTableScopeMarker(); - tree.insertElement(name, attributes); - tree.setInsertionMode('inTableBody'); - }; - - modes.inTable.startTagImplyTbody = function(name, attributes) { - this.startTagRowGroup('tbody', []); - tree.insertionMode.processStartTag(name, attributes); - }; - - modes.inTable.startTagTable = function(name, attributes) { - tree.parseError("unexpected-start-tag-implies-end-tag", - {startName: "table", endName: "table"}); - tree.insertionMode.processEndTag('table'); - if (!tree.context) tree.insertionMode.processStartTag(name, attributes); - }; - - modes.inTable.startTagStyleScript = function(name, attributes) { - modes.inHead.processStartTag(name, attributes); - }; - - modes.inTable.startTagInput = function(name, attributes) { - for (var key in attributes) { - if (attributes[key].nodeName.toLowerCase() == 'type') { - if (attributes[key].nodeValue.toLowerCase() == 'hidden') { - tree.parseError("unexpected-hidden-input-in-table"); - tree.insertElement(name, attributes); - // XXX associate with form - tree.openElements.pop(); - return; - } - break; - } - } - this.startTagOther(name, attributes); - }; - - modes.inTable.startTagForm = function(name, attributes) { - tree.parseError("unexpected-form-in-table"); - if (!tree.form) { - tree.insertElement(name, attributes); - tree.form = tree.currentStackItem(); - tree.openElements.pop(); - } - }; - - modes.inTable.startTagOther = function(name, attributes, selfClosing) { - tree.parseError("unexpected-start-tag-implies-table-voodoo", {name: name}); - tree.redirectAttachToFosterParent = true; - modes.inBody.processStartTag(name, attributes, selfClosing); - tree.redirectAttachToFosterParent = false; - }; - - modes.inTable.endTagTable = function(name) { - if (tree.openElements.inTableScope(name)) { - tree.generateImpliedEndTags(); - if (tree.currentStackItem().localName != name) { - tree.parseError("end-tag-too-early-named", {gotName: 'table', expectedName: tree.currentStackItem().localName}); - } - - tree.openElements.popUntilPopped('table'); - tree.resetInsertionMode(); - } else { - assert.ok(tree.context); - tree.parseError('unexpected-end-tag', {name: name}); - } - }; - - modes.inTable.endTagIgnore = function(name) { - tree.parseError("unexpected-end-tag", {name: name}); - }; - - modes.inTable.endTagOther = function(name) { - tree.parseError("unexpected-end-tag-implies-table-voodoo", {name: name}); - // Make all the special element rearranging voodoo kick in - tree.redirectAttachToFosterParent = true; - // Process the end tag in the "in body" mode - modes.inBody.processEndTag(name); - tree.redirectAttachToFosterParent = false; - }; - - modes.inTableText = Object.create(modes.base); - - modes.inTableText.flushCharacters = function() { - var characters = tree.pendingTableCharacters.join(''); - if (!isAllWhitespace(characters)) { - tree.redirectAttachToFosterParent = true; - tree.reconstructActiveFormattingElements(); - tree.insertText(characters); - tree.framesetOk = false; - tree.redirectAttachToFosterParent = false; - } else { - tree.insertText(characters); - } - tree.pendingTableCharacters = []; - }; - - modes.inTableText.processComment = function(data) { - this.flushCharacters(); - tree.setInsertionMode(tree.originalInsertionMode); - tree.insertionMode.processComment(data); - }; - - modes.inTableText.processEOF = function(data) { - this.flushCharacters(); - tree.setInsertionMode(tree.originalInsertionMode); - tree.insertionMode.processEOF(); - }; - - modes.inTableText.processCharacters = function(buffer) { - var characters = buffer.takeRemaining(); - characters = characters.replace(/\u0000/g, function(match, index){ - // @todo position - tree.parseError("invalid-codepoint"); - return ''; - }); - if (!characters) - return; - tree.pendingTableCharacters.push(characters); - }; - - modes.inTableText.processStartTag = function(name, attributes, selfClosing) { - this.flushCharacters(); - tree.setInsertionMode(tree.originalInsertionMode); - tree.insertionMode.processStartTag(name, attributes, selfClosing); - }; - - modes.inTableText.processEndTag = function(name, attributes) { - this.flushCharacters(); - tree.setInsertionMode(tree.originalInsertionMode); - tree.insertionMode.processEndTag(name, attributes); - }; - - modes.inTableBody = Object.create(modes.base); - - modes.inTableBody.start_tag_handlers = { - html: 'startTagHtml', - tr: 'startTagTr', - td: 'startTagTableCell', - th: 'startTagTableCell', - caption: 'startTagTableOther', - col: 'startTagTableOther', - colgroup: 'startTagTableOther', - tbody: 'startTagTableOther', - tfoot: 'startTagTableOther', - thead: 'startTagTableOther', - '-default': 'startTagOther' - }; - - modes.inTableBody.end_tag_handlers = { - table: 'endTagTable', - tbody: 'endTagTableRowGroup', - tfoot: 'endTagTableRowGroup', - thead: 'endTagTableRowGroup', - body: 'endTagIgnore', - caption: 'endTagIgnore', - col: 'endTagIgnore', - colgroup: 'endTagIgnore', - html: 'endTagIgnore', - td: 'endTagIgnore', - th: 'endTagIgnore', - tr: 'endTagIgnore', - '-default': 'endTagOther' - }; - - modes.inTableBody.processCharacters = function(data) { - modes.inTable.processCharacters(data); - }; - - modes.inTableBody.startTagTr = function(name, attributes) { - tree.openElements.popUntilTableBodyScopeMarker(); - tree.insertElement(name, attributes); - tree.setInsertionMode('inRow'); - }; - - modes.inTableBody.startTagTableCell = function(name, attributes) { - tree.parseError("unexpected-cell-in-table-body", {name: name}); - this.startTagTr('tr', []); - tree.insertionMode.processStartTag(name, attributes); - }; - - modes.inTableBody.startTagTableOther = function(name, attributes) { - // XXX any ideas on how to share this with endTagTable - if (tree.openElements.inTableScope('tbody') || tree.openElements.inTableScope('thead') || tree.openElements.inTableScope('tfoot')) { - tree.openElements.popUntilTableBodyScopeMarker(); - this.endTagTableRowGroup(tree.currentStackItem().localName); - tree.insertionMode.processStartTag(name, attributes); - } else { - // context case - tree.parseError('unexpected-start-tag', {name: name}); - } - }; - - modes.inTableBody.startTagOther = function(name, attributes) { - modes.inTable.processStartTag(name, attributes); - }; - - modes.inTableBody.endTagTableRowGroup = function(name) { - if (tree.openElements.inTableScope(name)) { - tree.openElements.popUntilTableBodyScopeMarker(); - tree.popElement(); - tree.setInsertionMode('inTable'); - } else { - tree.parseError('unexpected-end-tag-in-table-body', {name: name}); - } - }; - - modes.inTableBody.endTagTable = function(name) { - if (tree.openElements.inTableScope('tbody') || tree.openElements.inTableScope('thead') || tree.openElements.inTableScope('tfoot')) { - tree.openElements.popUntilTableBodyScopeMarker(); - this.endTagTableRowGroup(tree.currentStackItem().localName); - tree.insertionMode.processEndTag(name); - } else { - // context case - tree.parseError('unexpected-end-tag', {name: name}); - } - }; - - modes.inTableBody.endTagIgnore = function(name) { - tree.parseError("unexpected-end-tag-in-table-body", {name: name}); - }; - - modes.inTableBody.endTagOther = function(name) { - modes.inTable.processEndTag(name); - }; - - modes.inSelect = Object.create(modes.base); - - modes.inSelect.start_tag_handlers = { - html: 'startTagHtml', - option: 'startTagOption', - optgroup: 'startTagOptgroup', - select: 'startTagSelect', - input: 'startTagInput', - keygen: 'startTagInput', - textarea: 'startTagInput', - script: 'startTagScript', - '-default': 'startTagOther' - }; - - modes.inSelect.end_tag_handlers = { - option: 'endTagOption', - optgroup: 'endTagOptgroup', - select: 'endTagSelect', - caption: 'endTagTableElements', - table: 'endTagTableElements', - tbody: 'endTagTableElements', - tfoot: 'endTagTableElements', - thead: 'endTagTableElements', - tr: 'endTagTableElements', - td: 'endTagTableElements', - th: 'endTagTableElements', - '-default': 'endTagOther' - }; - - modes.inSelect.processCharacters = function(buffer) { - var data = buffer.takeRemaining(); - data = data.replace(/\u0000/g, function(match, index){ - // @todo position - tree.parseError("invalid-codepoint"); - return ''; - }); - if (!data) - return; - tree.insertText(data); - }; - - modes.inSelect.startTagOption = function(name, attributes) { - // we need to imply if " + name + "
    "; - }); + fs.readFile(filename, "binary", function(err, file) { + if(err) { + response.writeHead(500, {"Content-Type": "text/plain"}); + response.write(err + "\n"); + response.end(); + return; + } - res._hasBody && res.write(html.join("")); - res.end(); - return; - } - - fs.readFile(filename, "binary", function(err, file) { - if (err) { - res.writeHead(500, { "Content-Type": "text/plain" }); - res.write(err + "\n"); - res.end(); - return; - } - - var contentType = mime.lookup(filename) || "text/plain"; - res.writeHead(200, { "Content-Type": contentType }); - res.write(file, "binary"); - res.end(); - }); + var contentType = mime.lookup(filename) || "text/plain"; + response.writeHead(200, {"Content-Type": contentType}); + response.write(file, "binary"); + response.end(); }); + }); }).listen(port, ip); -function error(res, status, message, error) { - console.error(error || message); - res.writeHead(status, { "Content-Type": "text/plain" }); - res.write(message); - res.end(); -} - -function save(req, res, filePath) { - var data = ""; - req.on("data", function(chunk) { - data += chunk; - }); - req.on("error", function() { - error(res, 404, "Could't save file"); - }); - req.on("end", function() { - try { - fs.writeFileSync(filePath, data); - } - catch (e) { - return error(res, 404, "Could't save file", e); - } - res.statusCode = 200; - res.end("OK"); - console.log("saved ", filePath); - }); -} - -function getLocalIps() { - var os = require("os"); - - var interfaces = os.networkInterfaces ? os.networkInterfaces() : {}; - var addresses = []; - for (var k in interfaces) { - for (var k2 in interfaces[k]) { - var address = interfaces[k][k2]; - if (address.family === "IPv4" && !address.internal) { - addresses.push(address.address); - } - } - } - return addresses; -} - -console.log("http://" + (ip == "0.0.0.0" ? getLocalIps()[0] : ip) + ":" + port); - +console.log("http://localhost:" + port); diff --git a/static.py b/static.py index 7a2faf91..eb864596 100755 --- a/static.py +++ b/static.py @@ -32,9 +32,7 @@ import time import string import sys from os import path, stat, getcwd -from fnmatch import fnmatch from wsgiref import util -from wsgiref.validate import validator from wsgiref.headers import Headers from wsgiref.simple_server import make_server from optparse import OptionParser @@ -86,8 +84,6 @@ class Cling(object): not_modified = StatusApp('304 Not Modified', "") moved_permanently = StatusApp('301 Moved Permanently') method_not_allowed = StatusApp('405 Method Not Allowed') - success_no_content = StatusApp('204 No Content', "") - server_error = StatusApp('500 Internal Server Error') def __init__(self, root, **kw): """Just set the root and any other attribs passes via **kw.""" @@ -97,6 +93,9 @@ class Cling(object): def __call__(self, environ, start_response): """Respond to a request when called in the usual WSGI way.""" + if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'): + headers = [('Allow', 'GET, HEAD')] + return self.method_not_allowed(environ, start_response, headers) path_info = environ.get('PATH_INFO', '') full_path = self._full_path(path_info) if not self._is_under_root(full_path): @@ -110,23 +109,6 @@ class Cling(object): return self.moved_permanently(environ, start_response, headers) else: full_path = self._full_path(path_info + self.index_file) - try: - sz = int(environ['CONTENT_LENGTH']) - except: - sz = 0 - if environ['REQUEST_METHOD'] == 'PUT' and sz > 0: - for putglob in self.puttable: - if fnmatch(path_info, putglob): - data = environ['wsgi.input'].read(sz) - try: - with open(full_path, "wb") as f: f.write(data) - return self.success_no_content(environ, start_response) - except: - print sys.exc_info()[1] - return self.server_error(environ, start_response) - if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'): - headers = [('Allow', 'GET, HEAD')] - return self.method_not_allowed(environ, start_response, headers) content_type = self._guess_type(full_path) try: etag, last_modified = self._conditions(full_path, environ) @@ -209,90 +191,52 @@ def cling_wrap(package_name, dir_name, **kw): def command(): - usage = "%prog [--help] [-d DIR] [-l [HOST][:PORT]] [-p GLOB[,GLOB...]]" - parser = OptionParser(usage=usage, version="static 0.3.6") - parser.add_option("-d", "--dir", dest="rootdir", default=".", - help="Root directory to serve. Defaults to '.' .", metavar="DIR") - parser.add_option("-l", "--listen", dest="listen", default="127.0.0.1:8888", - help="Listen on this interface (given by its hostname or IP) and port."+ - " HOST defaults to 127.0.0.1. PORT defaults to 8888. "+ - "Leave HOST empty to listen on all interfaces (INSECURE!).", - metavar="[HOST][:PORT]") - parser.add_option("-p", "--puttable", dest="puttable", default="", - help="Comma or space-separated list of request paths for which to"+ - " permit PUT requests. Each path is a glob pattern that may "+ - "contain wildcard characters '*' and/or '?'. "+ - "'*' matches any sequence of characters, including the empty"+ - " string. '?' matches exactly 1 arbitrary character. "+ - "NOTE: Both '*' and '?' match slashes and dots. "+ - "I.e. --puttable=* makes every file under DIR writable!", - metavar="GLOB[,GLOB...]") - parser.add_option("--validate", dest="validate", action="store_true", - default=False, - help="Enable HTTP validation. You don't need this unless "+ - "you're developing static.py itself.") - + parser = OptionParser(usage="%prog DIR [HOST][:][PORT]", + version="static 0.3.6") options, args = parser.parse_args() - if len(args) > 0: + if len(args) in (1, 2): + if len(args) == 2: + parts = args[1].split(":") + if len(parts) == 1: + host = parts[0] + port = None + elif len(parts) == 2: + host, port = parts + else: + sys.exit("Invalid host:port specification.") + elif len(args) == 1: + host, port = None, None + if not host: + host = '0.0.0.0' + if not port: + port = 8888 + try: + port = int(port) + except: + sys.exit("Invalid host:port specification.") + app = Cling(args[0]) + try: + make_server(host, port, app).serve_forever() + except KeyboardInterrupt, ki: + print "Cio, baby!" + except: + sys.exit("Problem initializing server.") + else: parser.print_help(sys.stderr) sys.exit(1) - parts = options.listen.split(":") - if len(parts) == 1: - try: # if the the listen argument consists only of a port number - port = int(parts[0]) - host = None - except: # could not parse as port number => must be a host IP or name - host = parts[0] - port = None - elif len(parts) == 2: - host, port = parts - else: - sys.exit("Invalid host:port specification.") - if not host: - host = '0.0.0.0' - if not port: - port = 8888 +def test(): + from wsgiref.validate import validator + app = Cling(getcwd()) try: - port = int(port) - if port <= 0 or port > 65535: raise ValueError - except: - sys.exit("Invalid host:port specification.") - - puttable = set(path.abspath(p) for p in - options.puttable.replace(","," ").split()) - if puttable and host not in ('127.0.0.1', 'localhost'): - print("Permitting PUT access for non-localhost connections may be unwise.") - - options.rootdir = path.abspath(options.rootdir) - - for p in puttable: - if not p.startswith(options.rootdir): - sys.exit("puttable path '%s' not under root '%s'" % (p, options.rootdir)) - - # cut off root prefix from puttable paths - puttable = set(p[len(options.rootdir):] for p in puttable) - - app = Cling(options.rootdir, puttable=puttable) - - if options.validate: - app = validator(app) - - try: - print "Serving %s to http://%s:%d" % (options.rootdir, host, port) - if puttable: - print("The following paths (relative to server root) may be "+ - "OVERWRITTEN via HTTP PUT.") - for p in puttable: - print p - make_server(host, port, app).serve_forever() + print "Serving " + getcwd() + " to http://localhost:8888" + make_server('0.0.0.0', 8888, validator(app)).serve_forever() except KeyboardInterrupt, ki: + print "" print "Ciao, baby!" - except: - sys.exit("Problem initializing server: %s" % sys.exc_info()[1]) if __name__ == '__main__': - command() + test() diff --git a/tool/Readme.md b/tool/Readme.md deleted file mode 100644 index 28dd5166..00000000 --- a/tool/Readme.md +++ /dev/null @@ -1,26 +0,0 @@ -Helper Scripts for Ace -====================== - -To use this you need to install node.js. and run `npm install` in this directory. - - -# add_mode.js - - Run -``` -node add_mode.js ModeName "extension1|extension2|^FullName" -``` - to create all the files needed for a new mode named `ModeName` - this adds stubs for: - `ace/mode/mode_name.js` - `ace/mode/mode_name_hightlight_rules.js` - `ace/snippets/mode_name.js` - `ace/demo/kitchen_sink/docs/mode_name.extension1` - and adds entry for the new mode to `ace/ext/modelist.js` - - -# tmlanguage.js - -``` -node tmlanguage.js ./templates/dummy.JSON-tmLanguage -``` \ No newline at end of file diff --git a/tool/add_mode.js b/tool/add_mode.js deleted file mode 100644 index 879b9204..00000000 --- a/tool/add_mode.js +++ /dev/null @@ -1,106 +0,0 @@ -var fs = require('fs'); -var lib = require('./lib'); -var path = require('path'); - -function main(displayName, extRe) { - var name = lib.snakeCase(displayName).replace(/[^\w]/g, ""); - - /** demo **/ - var demoFileExt = extRe.split("|")[0] || name; - var demoFileName = demoFileExt[0] == "^" ? demoFileExt.substr(1) : name + "." + demoFileExt; - var demoFilePath = lib.AceRoot + "demo/kitchen-sink/docs/" + demoFileName; - fs.writeFileSync(demoFilePath, "TODO add a nice demo!\nTry to keep it short!", "utf8"); - console.log("Created demo file at: " + path.normalize(demoFilePath)); - - /** mode **/ - var template = fs.readFileSync(__dirname + "/templates/mode.js", "utf8"); - var modePath = lib.AceLib + "ace/mode/" + name + ".js"; - var text = lib.fillTemplate(template, { - languageHighlightFilename: name, - languagename: name, - lineCommentStart: "TODO", - blockCommentStart: "TODO", - blockCommentEnd: "TODO" - }); - fs.writeFileSync(modePath, text); - console.log("Created mode file at: " + path.normalize(modePath)); - - /** highlight rules **/ - template = fs.readFileSync(__dirname + "/templates/highlight_rules.js", "utf8"); - var hlPath = lib.AceLib + "ace/mode/" + name + "_highlight_rules.js"; - template = template.replace(/\/\* THIS[\s\S]*?\*{3}\/\s*/, ""); - text = lib.fillTemplate(template, { - language: name, - languageTokens: '{\n\ - start: [{\n\ - token: "string.start",\n\ - regex: \'"\',\n\ - next: "qstring"\n\ - }],\n\ - qstring: [{\n\ - token: "escape",\n\ - regex: /\\\\./,\n\ - }, {\n\ - token: "string.end",\n\ - regex: \'"\',\n\ - next: "start"\n\ - }],\n\ - }' - }); - fs.writeFileSync(hlPath, text); - console.log("Created mode file at: " + path.normalize(hlPath)); - - /** snippets **/ - template = fs.readFileSync(__dirname + "/templates/snippets.js", "utf8"); - var snipetsPath = lib.AceLib + "ace/snippets/" + name + ".js"; - text = lib.fillTemplate(template, { - languagename: name, - snippets: "" - }); - fs.writeFileSync(snipetsPath, text); - console.log("Created snippets file at: " + path.normalize(snipetsPath)); - - /** modelist **/ - var modelistPath = lib.AceLib + "ace/ext/modelist.js"; - var modelist = fs.readFileSync(modelistPath, "utf8").replace(/\r\n?/g, "\n"); - modelist = modelist.replace(/(supportedModes = {\n)([\s\S]*?)(\n^};)/m, function(_, m1, m2, m3) { - var langs = m2.split(/,\n/); - var offset = langs[0].trim().indexOf("["); - var padding = Array(Math.max(offset - displayName.length - 1, 0) + 1).join(" "); - var newLang = " " + displayName + ":" + padding + "[\"" + extRe + "\"]"; - langs = langs.concat(newLang).map(function(x) { - return { - value: x, - id: x.match(/[^"':\s]+/)[0].toLowerCase() - }; - }); - langs[langs.length - 1].isNew = true; - - langs = langs.filter(function(x) { - console.log(x.id, displayName) - return x.id != displayName.toLowerCase() || x.isNew; - }); - langs = langs.sort(function(a, b) { - return a.id.localeCompare(b.id); - }).map(function(x) { - return x.value; - }); - - return m1 + langs.join(",\n") + m3; - }); - fs.writeFileSync(modelistPath, modelist, "utf8"); - console.log("Updated modelist at: " + path.normalize(modelistPath)); -} - -if (!module.parent) { - var args = process.argv.slice(2); - var displayName = args[0]; - var extRe = args[1]; - if (!displayName || ! extRe) { - console.log("Usage: ModeName ext1|ext2"); - process.exit(1); - } -} else { - module.exports = main; -} - diff --git a/tool/lib.js b/tool/lib.js index 3d57b6e0..605922e0 100644 --- a/tool/lib.js +++ b/tool/lib.js @@ -1,182 +1,38 @@ var plist = require("plist"); var util = require("util"); -var url = require("url"); -var cson = require("cson"); - -var https = require("https"); -var http = require("http"); - -exports.parsePlist = function(xmlOrJSON, callback) { - var json; - if (xmlOrJSON[0] == "<") { - plist.parseString(xmlOrJSON, function(_, result) { - json = result[0]; - }); - } else { - try { - xmlOrJSON = xmlOrJSON.replace( - /("(?:\\.|[^"])*")|(?:,\s*)+([\]\}])|(\w+)\s*:|([\]\}]\s*[\[\{])|(\/\/.*|\/\*(?:[^\*]|\*(?=[^\/]))*?\*\/)/g, - function(_, str, extraComma, noQuote, missingComma, comment) { - if (comment) - return ""; - if (missingComma) - return missingComma[0] + "," + missingComma.slice(1); - return str || extraComma || '"' + noQuote + '":'; - }); - json = JSON.parse(xmlOrJSON); - } catch(e) { - json = cson.parse(xmlOrJSON); - } - } - callback && callback(json); - return json; -}; - +exports.parsePlist = function(themeXml, callback) { + var result = "" + plist.parseString(themeXml, function(_, theme) { + result = theme[0]; + callback && callback(theme[0]); + }); + return result; +} exports.formatJSON = function(object, initialIndent) { - return JSON.stringify(object, null, 4).replace(/^/gm, initialIndent||""); -}; - -exports.formatJS = function(object, initialIndent) { - return formatJS(object, 4, initialIndent); -}; - -function formatJS(object, indent, initialIndent) { - if (typeof indent == "number") - indent = Array(indent + 1).join(" "); + return util.inspect(object, false, 40).replace(/^/gm, initialIndent||"") - function $format(buffer, totalIndent, state, o) { - if (typeof o != "object" || !o) { - if (typeof o == "string") - buffer.push(JSON.stringify(o)); - else - buffer.push("" + o); - } - else if (Array.isArray(o)) { - buffer.push("[") - - var len = totalIndent.length - var oneLine = true; - for (var i = 0; i < o.length; i++) { - if (typeof o[i] == "string") { - len += o[i].length + 2 - } else if (!o[i]) { - len += (o[i] + "").length - } else { - oneLine = false; - break; - } - len += 2; - if (len > 60) { - oneLine = false; - break; - } - } - - for (var i = 0; i < o.length; i++) { - if (o[i] && typeof o[i] == "object") { - $format(buffer, totalIndent, state, o[i]); - if (i < o.length - 1) - buffer.push(", "); - } else { - if (oneLine) - i && buffer.push(" "); - else - buffer.push("\n", totalIndent + indent) - $format(buffer, totalIndent + indent, state, o[i]); - if (i < o.length - 1) - buffer.push(","); - } - - } - if (!oneLine && buffer[buffer.length - 1] != "}") - buffer.push("\n" + totalIndent) - buffer.push("]") - } - else { - var keys = Object.keys(o); - buffer.push("{", "\n"); - for (var i = 0; i < keys.length; i++) { - buffer.push(totalIndent + indent); - if (/^\w+$/.test(keys[i])) - buffer.push(keys[i]); - else - buffer.push(JSON.stringify(keys[i])); - buffer.push(": ") - - if (keys[i] == "regex" && typeof o[keys[i]] == "string") { - try { - var re = new RegExp(o[keys[i]]); - buffer.push("/" + re.source.replace(/\\.|\//g, function(f) { - return f.length == 1 ? "\\" + f : f; - }) + "/"); - } catch(e) { - $format(buffer, totalIndent + indent, state, o[keys[i]]); - } - } else { - $format(buffer, totalIndent + indent, state, o[keys[i]]); - } - - if (i < keys.length - 1) - buffer.push(",", "\n"); - } - buffer.push("\n", totalIndent, "}"); - } - } - var buffer = []; - $format(buffer, initialIndent || "", {}, object); - return buffer.join(""); } + exports.fillTemplate = function(template, replacements) { return template.replace(/%(.+?)%/g, function(str, m) { return replacements[m] || ""; }); -}; +} exports.hyphenate = function(str) { - return str.replace(/([A-Z])/g, "-$1").replace(/[_\s\-]+/g, "-").toLowerCase(); -}; - -exports.camelCase = function(str) { - return str.replace(/[\-_\s]+(.?)/g, function(x, y) {return y.toUpperCase()}); -}; - -exports.snakeCase = function(str) { - return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[_\s\-]+/g, "_").toLowerCase(); -}; + return str.replace(/([A-Z])/g, "-$1").replace(/_/g, "-").toLowerCase(); +} exports.quoteString = function(str) { return '"' + str.replace(/\\/, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\\n") + '"'; -}; +} exports.restoreJSONComments = function(objStr) { return objStr.replace(/^(\s*)comment: '(.*)'/gm, function(_, i, c) { - return i + "//" + c.replace(/\\n(\\t)*/g, "\n" + i + "//") + "\n" + i; + return i + "//" + c.replace(/\\n(\\t)*/g, "\n" + i + "//") + "\n" + i }).replace(/ \/\/ ERROR/g, '", // ERROR'); -}; - - -exports.download = function(href, callback) { - var options = url.parse(href); - var protocol = options.protocol === "https:" ? https : http; - console.log("connecting to " + options.host + " " + options.path); - var request = protocol.get(options, function(res) { - var data = ""; - res.setEncoding("utf-8"); - - res.on("data", function(chunk) { - data += chunk; - }); - - res.on("end", function(){ - callback(data); - }); - }); -}; - - -exports.AceRoot = __dirname + "/../"; -exports.AceLib = __dirname + "/../lib/"; +} diff --git a/tool/templates/mode.js b/tool/mode.tmpl.js similarity index 87% rename from tool/templates/mode.js rename to tool/mode.tmpl.js index 1cdabf15..bdf8065e 100644 --- a/tool/templates/mode.js +++ b/tool/mode.tmpl.js @@ -26,6 +26,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * + * + * Contributor(s): + * + * + * * ***** END LICENSE BLOCK ***** */ /* @@ -37,21 +42,23 @@ define(function(require, exports, module) { var oop = require("../lib/oop"); var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; var %language%HighlightRules = require("./%languageHighlightFilename%_highlight_rules").%language%HighlightRules; // TODO: pick appropriate fold mode var FoldMode = require("./folding/cstyle").FoldMode; var Mode = function() { - this.HighlightRules = %language%HighlightRules; + var highlighter = new %language%HighlightRules(); this.foldingRules = new FoldMode(); + this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$keywordList = highlighter.$keywordList; }; oop.inherits(Mode, TextMode); (function() { - // this.lineCommentStart = "%lineCommentStart%"; - // this.blockComment = {start: "%blockCommentStart%", end: "%blockCommentEnd%"}; + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; // Extra logic goes here. - this.$id = "ace/mode/%languageHighlightFilename%" }).call(Mode.prototype); exports.Mode = Mode; diff --git a/tool/mode_creator.html b/tool/mode_creator.html index 259ba64e..e2db56af 100644 --- a/tool/mode_creator.html +++ b/tool/mode_creator.html @@ -19,7 +19,7 @@ border-bottom: solid 1px; } .separator-h { - padding: 0 10px; + padding: 0 20px; } #closeBtn { background: rgba(245, 146, 146, 0.5); @@ -59,7 +59,6 @@ - @@ -71,7 +70,6 @@ - diff --git a/tool/mode_creator.js b/tool/mode_creator.js index 44aa67d0..3eda8c8c 100644 --- a/tool/mode_creator.js +++ b/tool/mode_creator.js @@ -2,11 +2,6 @@ define(function(require, exports, module) { /** creates globals intentionally to make things easily accessible from console **/ -require("ace/ext/language_tools"); -require("ace/config").setDefaultValues("editor", { - enableBasicAutocompletion: true, - enableSnippets: true -}); var net = require("ace/lib/net"); var Range = require("ace/range").Range; var util = require("demo/kitchen-sink/util"); @@ -53,7 +48,6 @@ util.bindDropdown("doc", function(value) { doclist.loadDoc(value, function(session) { if (session) { editor2.setSession(session); - updateSaveButtonState(null, editor2); } }); }); @@ -61,7 +55,6 @@ util.bindDropdown("doc", function(value) { var modeEl = document.getElementById("modeEl"); util.fillDropdown(modeEl, modelist.modes); var modeSessions = {}; - util.bindDropdown(modeEl, function(value) { if (modeSessions[value]) { editor1.setSession(modeSessions[value]); @@ -70,17 +63,14 @@ util.bindDropdown(modeEl, function(value) { } var hp = "./lib/ace/mode/" + value + "_highlight_rules.js"; net.get(hp, function(text) { + text = util.stripLeadingComments(text); + var session = new EditSession(text); session.setUndoManager(new UndoManager()); - modeSessions[value] = session; - session.setMode("ace/mode/javascript", function() { - if (session.getLine(0).match(/^\s*\//)) - session.toggleFoldWidget(0); // fold licence comment - }); + session.setMode("ace/mode/javascript"); editor1.setSession(modeSessions[value]); - updateSaveButtonState(null, editor1); schedule(); }); }); @@ -89,72 +79,28 @@ document.getElementById("syncToMode").onclick = function() { docEl.value = modelist.modesByName[modeEl.value].desc; docEl.onchange(); run(); -}; - -editor1.saveButton = document.getElementById("saveButton1"); -editor2.saveButton = document.getElementById("saveButton2"); -editor1.saveButton.editor = editor1; -editor2.saveButton.editor = editor2; - -editor1.saveButton.onclick = function() { - doclist.saveDoc({ - path: "./lib/ace/mode/" + modeEl.value + "_highlight_rules.js", - session: editor1.session - }, function(err) { - handleSaveResult(err, editor1); - }); -}; -editor1.commands.bindKey({ - win: "Ctrl-S", mac: "Cmd-s" -}, editor1.saveButton.onclick); -editor2.saveButton.onclick = function() { - doclist.saveDoc(docEl.value, function(err) { - handleSaveResult(err, editor2); - }); -}; -editor2.commands.bindKey({ - win: "Ctrl-S", mac: "Cmd-s" -}, editor2.saveButton.onclick); -function updateSaveButtonState(e, editor){ - editor.saveButton.disabled = editor.session.getUndoManager().isClean(); } -editor1.on("input", updateSaveButtonState); -editor2.on("input", updateSaveButtonState); - -function handleSaveResult(err, editor) { - if (err) { - return log( - "Write access to this file is disabled.\n"+ - "To enable saving your changes to disk, clone the Ace repository\n"+ - "and run the included web server with the --allow-save option\n"+ - "`node static.js --allow-save` or `static.py --puttable=*`" - ); - } - editor.session.getUndoManager().markClean(); - updateSaveButtonState(null, editor); -} - document.getElementById("perfTest").onclick = function() { - var lines = editor2.session.doc.getAllLines(); + var lines = editor2.session.doc.getAllLines() if (!lines.length) - return; + return while (lines.length < 1000) { - lines = lines.concat(lines); + lines = lines.concat(lines) } var tk = new Tokenizer(currentRules); - var testPerf = function(lines, tk) { - var state = "start"; + var testPerf = function(lines, tk){ + var state = "start" for (var i=0, l = lines.length; i |'\w+\b[+-]?\d'))/, merge:false}, - {include: "charTypes", merge:false}, - {token: "charclass", regex: /\[\^?/, push: "charclass", merge:false}, - {token: "alternation", regex: /\|/, merge:false}, - {include: "quantifiers", merge:false}, - {include: "groups", merge:false}, - {include: "xGroup", merge:true} - ], - charTypes: [ - {token: "char", regex: /\\([tvnrbfae]|[0-8]{1,3}|x[\dA-Fa-f]{2}|x7[\dA-Fa-f]{7})/, merge:false}, // todo \cx - {token: "charType", regex: /\.|\\[wWsSdDhH]/, merge:false}, - {token: "charProperty", regex: /\\p{\w+}/, merge:false}, - {token: "char", regex: /\\./, merge:false}, - ], - quantifiers: [ - {token: "quantifier", regex: /([?*+]|{\d+\b,?\d*}|{,\d+})[?+]?/, merge:false} - ], - charclass: [ - {include: "charTypes", merge:false}, - {token: "charclass.start", regex: /\[\^?/, push: "charclass", merge:false}, - {token: "charclass.end", regex: /\]/, next: "pop", merge:false} - ], - groups: [ - {token: "group", regex: /[(]([?](#|[imx\-]+:?|:|=|!|<=||<\w+>|'\w+'|))?|[)]/, - onMatch: function(val, state, stack) { - if (!stack.groupNumber) - stack.groupNumber = 1; - - var isStart = val !== ")"; - var t = {depth:0,type: isStart ? "group.start" : "group.end", value: val}; - t.groupType = val[2]; - - if (val == "(") { - t.number = stack.groupNumber++; - t.isGroup = true - } else if (t.groupType == "'" || (t.groupType == "<" && val.slice(-1) == ">")) { - t.name = val.slice(2, -1) - t.isGroup = true - } else if (t.groupType == ":") { - t.isGroup = true - } - - if (t.groupType && val.indexOf("x") != -1) { - var minus = val.indexOf("-"); - if (minus == -1 || minus > val.indexOf("x")) - stack.xGroup = t; - else - stack.xGroup = null; - } else if (!isStart && stack.xGroup && stack.xGroup == stack[0]) { - if (stack.xGroup.value.slice(-1) == ":") - stack.xGroup = null; - } - - if (isStart) { - if (stack.groupDepth) { - stack[0].hasChildren = true - } - stack.groupDepth = (stack.groupDepth||0)+1; - stack.unshift(t) - } else { - stack.groupDepth --; - t.start = stack.shift(t) - t.start.end = t - } - return [t] - }, merge:false - } - ], - xGroup: [ - {token: "text", regex:/\s+/, onMatch: function(val, state, stack) { - return stack.xGroup ? [] : "text" - }, merge: true}, - {token: "text", regex: /#/, onMatch: function(val, state, stack) { - if (stack.xGroup) { - this.next = "comment"; - stack.unshift(state); - return []; - } - this.next = ""; - return "text"; - }, merge: true} - ], - comment: [{ - regex: "[^\n\r]*|^", token: "", onMatch: function(val, state, stack) { - this.next = stack.shift(); - return []; - } - }] -} -r.normalizeRules() -var tmReTokenizer = new Tokenizer(r.getRules()); - -function tokenize(str) { - return tmReTokenizer.getLineTokens(str).tokens; -} - -function toStr(tokens) { return tokens.map(function(x){return x.value}).join("")} - - -exports.tokenize = tokenize; -exports.toStr = toStr; -exports.tmReTokenizer = tmReTokenizer; \ No newline at end of file diff --git a/tool/regexp_tokenizer_test.js b/tool/regexp_tokenizer_test.js deleted file mode 100644 index aa09ff12..00000000 --- a/tool/regexp_tokenizer_test.js +++ /dev/null @@ -1,30 +0,0 @@ -require("amd-loader"); -var assert = require("assert"); - -var tk = require("./regexp_tokenizer"); -var tokenize = tk.tokenize; -var toStr = tk.toStr; - -var logTokens = function(tokens) { - tokens.forEach(function(x) { - delete x.end - delete x.start - }) - console.log(tokens) -} - -assert.equal(toStr( - tokenize("(?x)c + +\n\ - # comment\n\ - (?-x) # (?x: 1 \n\ - (2) [ ] # a \n\ - 3 4) c#" - )), - "(?x)c++(?-x) # (?x:1(2)[ ]34) c#" - ) -assert.equal(toStr( - tokenize("(?x)\n\ - u # comment\n\ - ")), - "(?x)u" - ) diff --git a/tool/release.sh b/tool/release.sh deleted file mode 100644 index 52376914..00000000 --- a/tool/release.sh +++ /dev/null @@ -1,79 +0,0 @@ -pause() { - while true; do - read -p "$1 " yn - case $yn in - [Yy]* ) break;; - [Nn]* ) exit;; - * ) echo "Please answer yes or no.";; - esac - done -} - - - -cd `dirname $0`/.. -SOURCE=`pwd` - -CUR_VERSION=`node -e 'console.log(require("./package.json").version)'` -git --no-pager log --first-parent --oneline v$CUR_VERSION..master -echo "current version is $CUR_VERSION" -read -p "enter version number for the build " VERSION_NUM - -node -e " - var fs = require('fs'); - var version = '$VERSION_NUM'; - function replaceVersion(str) { - return str.replace(/(['\"]?version['\"]?\s*[:=]\s*['\"])[\\d.\\w\\-]+(['\"])/, function(_, m1, m2) { - return m1 + version + m2; - }); - } - function update(path, replace) { - var pkg = fs.readFileSync(path, 'utf8'); - pkg = (replace || replaceVersion)(pkg); - fs.writeFileSync(path, pkg, 'utf8'); - } - update('package.json'); - update('build/package.json'); - update('./lib/ace/ext/menu_tools/generate_settings_menu.js'); - update('ChangeLog.txt', function(str) { - var date='"`date +%Y.%m.%d`"'; - return date + ' Version ' + version + '\n' + str.replace(/^\d+.*/, '').replace(/^\n/, ''); - }); -" - -pause "versions updated. do you want to start build script? [y/n]" - -node Makefile.dryice.js full -cd build -git add . -git commit --all -m "package `date +%d.%m.%y`" - - -echo "build task completed." -pause "continue creating the tag for v$VERSION_NUM [y/n]" -if [[ ${VERSION_NUM} != *"-"* ]]; then - git tag "v"$VERSION_NUM -fi - -pause "continue pushing to github? [y/n]" - -git push --progress --tags "origin" HEAD:gh-pages HEAD:master - -echo "build repository updated" - -pause "continue update ace repo? [y/n]" -cd .. - - -echo "new commit added" -pause "continue creating the tag for v$VERSION_NUM [y/n]" -if [[ ${VERSION_NUM} != *"-"* ]]; then - git tag "v"$VERSION_NUM -fi - -pause "continue pushing to github? [y/n]" - -git push --progress --tags "origin" HEAD:gh-pages HEAD:master -echo "All done!" -pause "May I go now? [y/n]" - diff --git a/tool/templates/snippets.js b/tool/snippets.tmpl.js similarity index 100% rename from tool/templates/snippets.js rename to tool/snippets.tmpl.js diff --git a/tool/templates/dummy.JSON-tmLanguage b/tool/templates/dummy.JSON-tmLanguage deleted file mode 100644 index cb58b29b..00000000 --- a/tool/templates/dummy.JSON-tmLanguage +++ /dev/null @@ -1,45 +0,0 @@ -// [PackageDev] target_format: plist, ext: tmLanguage -{ - "name": "Dummy", - "scopeName": "source.dummy", - "fileTypes": ["dummy"], - "patterns": [ - { - "include": "#string" - }, { - "include": "#escapes" - } - ], - "repository": { - "escapes": { - "patterns": [ - { - "match": "\\\\[nrt\\\\\\$\\\"']", - "name": "keyword.dummy" - } - ] - }, - "string": { - "beginCaptures": { - "0": { - "name": "punctuation.definition.string.begin.dummy" - } - }, - "endCaptures": { - "0": { - "name": "punctuation.definition.string.end.dummy" - } - }, - "contentName": "meta.string-contents.quoted.double.dummy", - "name": "string.quoted.double.dummy", - "end": "'''", - "begin": "'''", - "patterns": [ - { - "include": "#escapes" - } - ], - "comment": "This is a comment" - } - } -} \ No newline at end of file diff --git a/tool/templates/theme.css b/tool/theme.tmpl.css similarity index 84% rename from tool/templates/theme.css rename to tool/theme.tmpl.css index 8515d0c3..58d16360 100644 --- a/tool/templates/theme.css +++ b/tool/theme.tmpl.css @@ -1,8 +1,8 @@ /* THIS THEME WAS AUTOGENERATED BY Theme.tmpl.css (UUID: %uuid%) */ .%cssClass% .ace_gutter { - background: %gutterBg%; - color: %gutterFg%; + background: #e8e8e8; + color: #333; } .%cssClass% .ace_print-margin { @@ -16,7 +16,12 @@ } .%cssClass% .ace_cursor { - color: %cursor%; + border-left: 2px solid %cursor%; +} + +.%cssClass% .ace_overwrite-cursors .ace_cursor { + border-left: 0px; + border-bottom: 1px solid %overwrite%; } .%cssClass% .ace_marker-layer .ace_selection { diff --git a/tool/templates/theme.js b/tool/theme.tmpl.js similarity index 100% rename from tool/templates/theme.js rename to tool/theme.tmpl.js diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index b5d8b851..d6e5fd03 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -1,330 +1,8 @@ -require("amd-loader"); - var fs = require("fs"); var util = require("util"); var lib = require("./lib"); -var pathlib = require("path"); var parseLanguage = lib.parsePlist; -var tk = require("./regexp_tokenizer"); -var tokenize = tk.tokenize; -var toStr = tk.toStr; - -function last(array) {return array[array.length - 1]} - -function convertHexEscape(tokens) { - var inChClass = false; - tokens.forEach(function(t) { - if (t.type == "charclass") - inChClass = true; - else if (t.type == "charclass.end") - inChClass = false; - else if (t.type == "charType"){ - if (t.value == "\\h") { - t.type = "text"; - t.value = inChClass ? "\\da-fA-F" : "[\\da-fA-F]"; - } - else if (t.value == "\\H") { - if (inChClass) { - console.warn("can't convert \\H in charclass"); - return; - } - t.type = "text"; - t.value = "[^\\da-fA-F]"; - } - } - }); - return tokens; -} - -function convertNewLinesTo$(str) { - var tokens = tokenize(str); - for (var i = 0; i < tokens.length; i++) { - var t= tokens[i]; - if (t.type == "char" && t.value == "\\n") { - var p = tokens[i + 1] || {}; - if (p.type != "quantifier") { - t.value = "$"; - while (p.value == "\\n" || p.type == "quantifier") { - p.value = ""; - p = tokens[++i + 1] || {}; - } - } else if (/\?|\*|{,|{0,/.test(p.value)) { - t.value = p.value = ""; - } else - p.value = ""; - } - } - return toStr(tokens).replace(/[$]+/g, "$"); -} - -function convertCharacterTypes(str) { - var tokens = tokenize(str); - tokens = convertHexEscape(tokens); - - var warn = false; - tokens.forEach(function(t){ - if (t.type == "quantifier") { - var val = t.value; - if (val.slice(-1) == "+" && val.length > 1) { - t.value = val.slice(0, -1); - warn = val; - } - } - }); - if (warn) - console.log("converted possesive quantifier " + warn + " to *"); - return toStr(tokens); -} - -function removeInlineFlags(str, rule) { - var tokens = tokenize(str); - var caseInsensitive = false; - tokens.forEach(function(t, i) { - if (t.type == "group.start" && /[imsx]/.test(t.value)) { - if (/i/.test(t.value)) - caseInsensitive = true; - t.value = t.value.replace(/[imsx\-]/g, ""); - var next = tokens[i + 1]; - if (next && next.type == "group.end") { - t.value = next.value = ""; - } - } - }); - if (caseInsensitive && rule) - rule.caseInsensitive = true; - return toStr(tokens); -} - -function convertToNonCapturingGroups(str) { - var tokens = tokenize(str); - tokens.forEach(function(t, i) { - if (t.type == "group.start" && t.value == "(") - t.value += "?:"; - }); - return toStr(tokens); -} - -function simplifyNonCapturingGroups(str) { - var tokens = tokenize(str); - var t = tokens[0] || {}; - if (t.type == "group.start" && t.value == "(?:" - && t.end == last(tokens)) { - t.value = t.end.value = ""; - } - var i = 0; - function iter(f) { - for (i = 0; i < tokens.length; i++) - f(tokens[i]); - } - function iterGroup(end, f) { - for (var i1 = i + 1; i1 < tokens.length; i1++) { - var t = tokens[i1]; - if (t == end) - break; - var index = f && f(t); - if (index > i1) - i1 = index; - } - return i1; - } - - iter(function (t) { - if (t.type == "group.start" && t.value == "(?:") { - if (!t.end) - return console.error("malformed regex: " + str); - - var canRemove = true; - var next = tokens[tokens.indexOf(t.end, i) + 1]; - if (next && next.type == "quantifier") - return; - iterGroup(t.end, function(t) { - if (t.type == "alternation") - canRemove = false; - else if (t.type == "group.start" && t.end) - return iterGroup(t.end); - }); - if (canRemove) - t.value = t.end.value = ""; - } - }); - - return toStr(tokens); -} - -function removeLookBehinds(str) { - var tokens = tokenize(str); - var toRemove = null; - tokens.forEach(function(t, i) { - if (!toRemove && t.type == "group.start" && / i) - i = i1; - } - function lst(t) {return t[t.length - 1]} - function iter(f) { - for (i = 0; i < tokens.length; i++) - f(tokens[i]); - } - function iterGroup(end, f) { - for (var i1 = i + 1; i1 < tokens.length; i1++) { - var t = tokens[i1]; - if (t == end) - break; - f(t); - } - } - function peek() { return tokens[i + 1] || {}} - - // groupify - iter(function(t){ - if (t.type == "group.start") { - tryClose(); - isStart = true; - if (!t.hasChildren || t.isSpecial) - skip(t); - } else if (t.type == "group.end") { - isStart = true; - tryClose(); - } else if (t.type == "alternation") { - isStart = true; - tryClose(); - } else if (t.type != "anchor" && t.type != "quantifier"){ - tryOpen(); - } - }); - tryClose(); - - // remove redundand groups - var names = [defaultName]; - iter(function(t){ - if (t.type == "group.start" && !t.isSpecial) { - var captureName = captures[t.number]; - - if (!t.hasChildren) { - t.tokenName = captureName || lst(names); - skip(t); - } else { - var hasCapture = false; - iterGroup(t.end, function(t1) { - if (t1.type == "group.start" && captures[t1.number]) - hasCapture = true; - }); - if (hasCapture) { - t.value = "(?:"; - if (captureName) { - names.push(captureName); - t.isTokenGroup = true; - } - } else { - t.tokenName = captureName || lst(names); - iterGroup(t.end, function(t1) { - if (t1.value == "(") - t1.value = "(?:"; - }); - } - } - } else if (t.type == "group.end") { - if (t.start.isTokenGroup) - names.pop(); - } - }); - - // wrap capturing groups with quantifier - iter(function(t){ - if (t.type == "group.end" && t.start.value == "(" && peek().type == "quantifier") { - peek().value += ")"; - t.start.value += "(?:"; - } - }); - - names = []; - tokens.forEach(function(t) { - if (t.value == "(" || t.value == "((?:" ) - t.tokenName && names.push(t.tokenName); - }); - return { - names: names, - regex: toStr(tokens) - }; -} - -/***** converter */ function logDebug(string, obj) { console.log(string, obj); @@ -335,6 +13,7 @@ function logDebug(string, obj) { // for tracking token states var states = {start: []}; +var stateName = "start"; function processRules(rules){ if (rules.patterns) @@ -361,38 +40,29 @@ function processPatterns(pl) { return pl.map(processPattern); } function processPattern(p) { + if (p.end == "(?!\\G)" && p.patterns && p.patterns.length == 1) { var rule = processPattern(p.patterns[0]); } - else if (p.begin != null && p.end != null) { - convertBeginEndBackrefs(p); - - var rule = simpleRule(p.begin, p.name, p.beginCaptures || p.captures); + else if (p.begin && p.end) { + var rule = simpleRule(p.begin, p.name, p.beginCaptures || p.captures) var next = processPatterns(p.patterns || []); var endRule = simpleRule(p.end, p.name, p.endCaptures || p.captures); endRule.next = "pop"; - if (p.applyEndPatternLast) - next.push(endRule); - else - next.unshift(endRule); + next.push(endRule); if (p.name || p.contentName) next.push({defaultToken: p.name || p.contentName}); rule.push = next; - - rule = removeIncludeSelf(rule); } else if (p.match) { - var rule = simpleRule(p.match, p.name, p.captures); + var rule = simpleRule(p.match, p.name, p.captures) } else if (p.include) { var rule = {include: p.include}; } - else { - var rule = {todo: p}; - } if (p.comment) rule.comment = (rule.comment || "") + p.comment; @@ -403,269 +73,106 @@ function processPattern(p) { } function simpleRule(regex, name, captures) { name = name || "text"; - var rule = {token: "", regex: ""}; + var rule = {}; - var origRegex = regex; - regex = transformRegExp(origRegex, rule); + var origRegex = regex + regex = transformRegExp(regex, rule); if (captures) { var tokenArray = []; Object.keys(captures).forEach(function(x){ tokenArray[x] = captures[x] && captures[x].name; }); - if (tokenArray.length == 1) { name = tokenArray[0]; } else { - var fixed = fixGroups(tokenArray, name, regex); - name = fixed.names; - regex = fixed.regex; - if (name.length == 1) - name = name[0]; + for (var i = 0; i < tokenArray.length; i++) + if (!tokenArray[i]) + tokenArray[i] = name; + name = tokenArray; + rule.todo = "fix grouping"; } } - if (typeof name == "string") - regex = convertToNonCapturingGroups(regex); - - regex = simplifyNonCapturingGroups(regex); - try {new RegExp(regex);} catch(e) { rule.TODO = "FIXME: regexp doesn't have js equivalent"; - rule.originalRegex = origRegex; - - // lookbehinds are mostly used to force ordering - // regex = removeLookBehinds(regex); + rule.originalRegex = origRegex } rule.token = name; rule.regex = regex; return rule; } -function removeIncludeSelf(rule) { - if (!rule.push) - return rule; - var hasSelfInclude = false; - var escapeRule = null; - var complexSelfInclude = false; - rule.push.forEach(function(sub) { - if (sub.include == "$self") { - hasSelfInclude = true; - } else if (sub.defaultToken) { - return; - } else if (sub.next == "pop") { - escapeRule = sub; - } else - complexSelfInclude = true; - }); - - if (hasSelfInclude) { - console.warn("can't convert include $self"); - return {todo: rule}; - - if (complexSelfInclude) { - console.warn("can't convert include $self"); - rule.toDo = "include $self not fully supported"; - return rule; - } - console.warn("include $self not fully supported"); - delete rule.push; - delete escapeRule.next; - rule.includeSelf = true; - escapeRule.includeSelf = true; - return [rule, escapeRule]; - } - return rule; -} // regex transformation function removeXFlag(str) { - var tokens = tokenize(str); - return toStr(tokens); + if (str && str.slice(0,4) == "(?x)") { + str = str.replace(/\\.|\[([^\]\\]|\\.)*?\]|\s+|(?:#[^\n]*)/g, function(s) { + if (s[0] == "[") + return s; + if (s[0] == "\\") + return /[#\s]/.test(s[1]) ? s[1] : s; + return ""; + }).substr(4); + } + return str; } function transformRegExp(str, rule) { - str = convertNewLinesTo$(str); - - str = removeInlineFlags(str, rule); - + str = removeXFlag(str); + //str = str.replace(/\\n\$|\$\\n/g, '$'); + str = str.replace(/\\n(?!\?).?/g, '$'); // replace newlines by $ except if its postfixed by ? + if (/\(\?[i]\:|\(?\w*i\w*\)/g.test(str)) { + str = str.replace(/\(\?[ims\-]\:/g, "(?:"); // checkForInvariantRegex + str = str.replace(/\(\?[imsx\-]\)/g, ""); + rule && (rule.caseInsensitive = true); + } str = str.replace(/(\\[xu]){([a-fA-F\d]+)}/g, '$1$2'); - - str = convertCharacterTypes(str, rule); - - checkForNamedCaptures(str); - return str; } // function extractPatterns(tmRules) { - return processRules(tmRules); + var patterns = processRules(tmRules); + return lib.restoreJSONComments(lib.formatJSON(patterns, " ")); + } -function detectLoops(states) { - var data = {}; - var keys = Object.keys(states); - var flattenedStates = {}; - function addRef(item, name) { - if (item.refs.indexOf(name) == -1) - item.refs.push(name); - } - function anonStateId(name, next) { - var i = 0, old = name; - while (flattenedStates[name] || states[name]) { - name = old + "_" + i++; - } - // console.log(old, name) - return name; - } - function addState(key, rules) { - if (rules && !flattenedStates[key]) - flattenedStates[key] = rules; - return rules || flattenedStates[key]; - } - - - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - var state = addState(key, states[key]); - - var item = data[key] || (data[key] = {/* name: key, */ refs: []}); - state.forEach(function(rule) { - var next = rule.push || rule.next; - if (next == "pop") { - // nothing - } else if (typeof next == "string") { - addRef(item, next); - } else if (next) { - var anonId = anonStateId(key, next); - addState(anonId, next); - if (rule.push) - addRef(item, anonId); - keys.push(anonId); - } else if (rule.include) { - addRef(item, rule.include); - } - }); - } - - - var cycles = []; - function addPath(start, path) { - var node = data[start]; - path.push(start); - if (!node || !node.refs) - console.log(start); - var i = path.indexOf(start); - if (i > -1 && i != path.length - 1 || start == "$self" || start == "$base") { - if (i != -1) - path = path.slice(i); - for (var j = 0; j < cycles.length; j++) { - if (cycles[j] + "" == path + "") - return; - } - return cycles.push(path); - } - - if (!node || !node.refs || !node.refs.length || path.length>30) - return; - node.refs.forEach(function(x) { - addPath(x, path.concat()); - }); - } - addPath("start", []); - - console.error(cycles.join("\n")); -} - - -function test(fileName) { - console.log("testing highlighter"); - try { - var module = require(fileName); - var Mode = module[Object.keys(module)[0]]; - var mode = new Mode(); - mode.getTokenizer().getLineTokens("hello world"); - } catch(e) { - console.log(e); - } -} - -function guessComment(patterns) { - var comment = {}; - for (var i in patterns) { - var state = patterns[i]; - state.forEach(function(r) { - if (typeof r.token == "string") { - if (/\bcomment\b/.test(r.token)) { - comment.line = r.regex; - } - } - }); - } - - return comment; -} // cli stuff -var modeTemplate = fs.readFileSync(__dirname + "/templates/mode.js", "utf8"); -var modeHighlightTemplate = fs.readFileSync(__dirname + "/templates/highlight_rules.js", "utf8"); +var modeTemplate = fs.readFileSync(__dirname + "/mode.tmpl.js", "utf8"); +var modeHighlightTemplate = fs.readFileSync(__dirname + "/mode_highlight_rules.tmpl.js", "utf8"); -function fetchAndConvert(name) { - console.log("Converting " + name); - if (/^http/.test(name)) { - if (/:\/\/github.com/.test(name)) { - name = name.replace(/\/blob\//, "/").replace("github.com", "raw.github.com"); - } - return lib.download(name, function(data) { - convertTmLanguage(name, data); - }); - } - var path = /^(\/|\w:)/.test(name) ? name : process.cwd() + "/" + name; - var langStr = fs.readFileSync(path, "utf8"); - convertTmLanguage(name, langStr); -} +function convertLanguageFile(name) { + var path = /^(\/|\w:)/.test(name) ? name : process.cwd() + "/" + name + var tmLanguage = fs.readFileSync(path, "utf8"); + parseLanguage(tmLanguage, function(language) { + var languageHighlightFilename = language.name.replace(/[-_]/g, "").toLowerCase(); + var languageNameSanitized = language.name.replace(/-/g, ""); + var languageHighlightFile = __dirname + "/../lib/ace/mode/" + languageHighlightFilename + "_highlight_rules.js"; + var languageModeFile = __dirname + "/../lib/ace/mode/" + languageHighlightFilename + ".js"; -function convertTmLanguage(name, langStr) { - parseLanguage(langStr, function(language) { - var highlighterFilename = lib.snakeCase(language.name).replace(/[^\w]/g, ""); - var languageNameSanitized = lib.camelCase(language.name).replace(/[^\w]/g, ""); - - require("./add_mode")(languageNameSanitized, (language.fileTypes || []).join("|")); - - var highlighterFile = pathlib.normalize(lib.AceLib + "ace/mode/" + highlighterFilename + "_highlight_rules.js"); - var modeFile = pathlib.normalize(lib.AceLib + "ace/mode/" + highlighterFilename + ".js"); + console.log("Converting " + name + " to " + languageHighlightFile); if (devMode) { console.log(util.inspect(language.patterns, false, 4)); console.log(util.inspect(language.repository, false, 4)); } - var patterns = extractPatterns(language); - detectLoops(patterns); - - // var uuid = language.uuid - delete language.uuid; - delete language.patterns; - delete language.repository; - - var comment = guessComment(patterns); var languageMode = lib.fillTemplate(modeTemplate, { language: languageNameSanitized, - languageHighlightFilename: highlighterFilename, - lineCommentStart: JSON.stringify(comment.line || "//"), - blockCommentStart: JSON.stringify(comment.start || "/*"), - blockCommentEnd: JSON.stringify(comment.end || "*/") + languageHighlightFilename: languageHighlightFilename }); + var patterns = extractPatterns(language); + var languageHighlightRules = lib.fillTemplate(modeHighlightTemplate, { language: languageNameSanitized, - languageTokens: lib.formatJS(patterns, " ").trim(), + languageTokens: patterns.trim(), uuid: language.uuid, - name: name, - metaData: lib.formatJS(language, "").trim() + name: name }); if (devMode) { @@ -674,24 +181,17 @@ function convertTmLanguage(name, langStr) { console.log("Not writing, 'cause we're in dev mode, baby."); } else { - fs.writeFileSync(highlighterFile, languageHighlightRules); - fs.writeFileSync(modeFile, languageMode); - console.log("created file " + highlighterFile); - test(modeFile); + fs.writeFileSync(languageHighlightFile, languageHighlightRules); + fs.writeFileSync(languageModeFile, languageMode); } }); } -if (!module.parent) { - var args = process.argv.splice(2); - var devMode = args[0] == "--dev"; - if (devMode) - args.shift(); - if (args.length < 1) { - console.error("Usage: node tmlanguage.js [--dev] path/or/url/to/syntax.file ..."); - process.exit(1); - } - args.forEach(fetchAndConvert); -} else { - exports.fetchAndConvert = fetchAndConvert; +var args = process.argv.splice(2); +var tmLanguageFile = args[0]; +var devMode = args[1]; +if (tmLanguageFile === undefined) { + console.error("Please pass in a language file via the command line."); + process.exit(1); } +convertLanguageFile(tmLanguageFile); \ No newline at end of file diff --git a/tool/tmtheme.js b/tool/tmtheme.js index c784eec7..c01fb16f 100755 --- a/tool/tmtheme.js +++ b/tool/tmtheme.js @@ -94,6 +94,7 @@ function extractStyles(theme) { "printMargin": "#e8e8e8", "background": parseColor(globalSettings.background), "foreground": parseColor(globalSettings.foreground), + "overwrite": parseColor(globalSettings.caret), "gutter": "#e8e8e8", "selection": parseColor(globalSettings.selection), "step": "rgb(198, 219, 174)", @@ -106,7 +107,7 @@ function extractStyles(theme) { for (var i=1; i.css rules, // (because some exist, for collab1 and ace_indentation_guide try { - var outThemeCss = fs.readFileSync(outputDirectory + "/" + name + ".css"); + var outThemeCss = fs.readFileSync(__dirname + "/../lib/ace/theme/" + name + ".css"); var oldRules = cssParse(outThemeCss).stylesheet.rules; var newRules = cssParse(css).stylesheet.rules; @@ -337,7 +310,6 @@ function convertTheme(name, tmThemePath, outputDirectory) { css = cssStringify({stylesheet: {rules: oldRules}}, { compress: false }); } catch(e) { console.log("Creating new file: " + name + ".css") - css = cssStringify(cssParse(css), { compress: false }); } var js = fillTemplate(jsTemplate, { @@ -347,25 +319,13 @@ function convertTheme(name, tmThemePath, outputDirectory) { isDark: styles.isDark }); - fs.writeFileSync(outputDirectory + "/" + name + ".js", js); - fs.writeFileSync(outputDirectory + "/" + name + ".css", css); + fs.writeFileSync(__dirname + "/../lib/ace/theme/" + name + ".js", js); + fs.writeFileSync(__dirname + "/../lib/ace/theme/" + name + ".css", css); }) } -if (process.argv.length > 1) { - var args = process.argv.splice(2); - if (args.length < 3) { - console.error("Usage: node tmtheme.js [theme_name, path/to/theme.tmTheme path/to/output/directory]"); - process.exit(1); - } - var name = args[0]; - var themePath = args[1]; - var outputDirectory = args[2]; - convertTheme(name, themePath, outputDirectory); -} else { - for (var name in themes) { - convertBuiltinTheme(name); - } +for (var name in themes) { + convertTheme(name); } var sortedUnsupportedScopes = {}; diff --git a/tool/tmthemes/Katzenmilch.tmTheme b/tool/tmthemes/Katzenmilch.tmTheme deleted file mode 100644 index 3878ffe9..00000000 --- a/tool/tmthemes/Katzenmilch.tmTheme +++ /dev/null @@ -1,399 +0,0 @@ - - - - - name - Katzen-Milch - comment - Those silly germans and their cat milk! Ghee wizz! - settings - - - settings - - background - #f3f2f3 - caret - #100011 - foreground - #0f0009ff - invisibles - #000000 - lineHighlight - #ffffff - selection - #6405D044 - selectionBorder - #8425f0 - bracketContentsOptions - underline - tagsForeground - #0f0009ff - tagsOptions - underline - - - - name - Parenthesis - scope - punctuation.definition.list - settings - - fontStyle - - foreground - #940494 - background - #4444940a - - - - name - Comment - scope - comment - settings - - fontStyle - italic - foreground - #404f50aa - background - #5f0fff02 - - - - name - String - scope - string - settings - - foreground - #5a5f9b - background - #aaafdb09 - - - - name - Number - scope - constant.numeric - settings - - foreground - #4f827bee - background - #77c2bb0f - - - - name - User-defined Constant - scope - constant.character, constant.other - settings - - foreground - #025f69ff - background - #7f229910 - - - - name - Built-in Constant - scope - constant.language - settings - - fontStyle - - foreground - #7D7e52 - background - #bDbe820f - - - - name - Storage Modifier - scope - storage.modifier - settings - - fontStyle - bold - foreground - #7B5D8f - background - #9B9FfD0a - - - - name - Storage - scope - storage - settings - - fontStyle - bold - foreground - #7B5cbfff - background - #8B5Ddf0d - - - - name - Function Name - scope - entity.name.function - settings - - fontStyle - - foreground - #025f49f7 - background - #22ff491f - - - - name - Support Function - scope - support.function - settings - - foreground - #9D7e62 - background - #bDbe820a - - - - name - Misc Function - scope - entity.name.function.misc - settings - - foreground - #939469 - background - #E3E4A90a - - - - name - Predicate Function - scope - entity.name.function.predicate - settings - - foreground - #856F63 - background - #A5DF930a - - - - name - Input/Output Function - scope - entity.name.function.io - settings - - foreground - #aF938C - background - #DFB3AC0a - - - - name - External Symbol - scope - variable.other.external-symbol - settings - - foreground - #7BaFaD - background - #BBDFDD0a - - - - name - Variable - scope - variable.language, variable.other - settings - - foreground - #316fcf - background - #3aafff0a - - - - name - Parameter Variable - scope - variable.parameter - settings - - fontStyle - italic - foreground - #33969fdd - background - #05d6f90b - - - - name - Keyword - scope - keyword - settings - - foreground - #674Aa8 - background - #A3AAD80e - - - - name - Class Name - scope - entity.name.class - settings - - fontStyle - bold - foreground - #B9986F - background - #B998DF22 - - - - name - Structure Name - scope - entity.name.structure - settings - - foreground - #22af9d - background - #B998DF0a - - - - name - Type Name - scope - entity.name.type - settings - - foreground - #af47a9 - background - #af77a90d - - - - name - Class name - scope - entity.name.class, entity.name.type.class - settings - - foreground - #cc4357 - background - #ffddff92 - - - - name - Support Class - scope - support.class - settings - - foreground - #ef6aa7ff - background - #ef6aa710 - - - - name - Invalid - scope - invalid - settings - - background - #CC1B27 - foreground - #DFDFD5 - - - - - name - ♦ String embedded-source - scope - string source - settings - - fontStyle - italic - foreground - #13499fdd - background - #0099ff0a - - - - name - Tag name - scope - entity.name.tag - settings - - foreground - #3976a2 - background - #49a6d20a - - - - name - Tag attribute - scope - entity.other.attribute-name - settings - - fontStyle - - foreground - #4946c2ee - background - #4986c209 - - - - - diff --git a/tool/tmthemes/Kuroir Theme.tmTheme b/tool/tmthemes/Kuroir Theme.tmTheme deleted file mode 100644 index 36acd588..00000000 --- a/tool/tmthemes/Kuroir Theme.tmTheme +++ /dev/null @@ -1,916 +0,0 @@ - - - - - author - Stanley Rost - comment - Kuroir - name - Kuroir Theme - settings - - - settings - - background - #E8E9E8 - caret - #202020 - foreground - #363636 - invisibles - #0000004A - lineHighlight - #CBDC2F38 - selection - #F5AA0091 - - bracketsForeground - #C41717 - bracketsOptions - foreground underline - - bracketContentsForeground - #C41717 - bracketContentsOptions - foreground underline background - - guide - #8F8F8F - activeGuide - #FA2828 - - tagsOptions - stippled_underline - - - - name - Comment - scope - comment - settings - - background - #DCDCDC8F - fontStyle - - foreground - #949494E8 - - - - name - Regions - scope - comment.line.region - settings - - background - #E9D6DC85 - fontStyle - - foreground - #A54776 - - - - name - Line Marker - scope - comment.line.marker.php - settings - - background - #E9E4BE - foreground - #668D68 - - - - name - Todo - scope - comment.line.todo.php - settings - - background - #D9EAB8 - fontStyle - - foreground - #456E48 - - - - name - FIXME - scope - comment.line.fixme.php - settings - - background - #E1D0CA - fontStyle - - foreground - #880006 - - - - name - Constant - scope - constant - settings - - foreground - #CD6839 - - - - name - Entity - scope - entity - settings - - background - #E8E9E8 - fontStyle - - foreground - #8B4726 - - - - name - Storage - scope - storage - settings - - fontStyle - - foreground - #A52A2A - - - - name - Keyword Control - scope - keyword.control - settings - - foreground - #CD3700 - - - - name - Library Function - scope - support.function - variable, keyword.other.special-method.ruby - settings - - foreground - #B03060 - - - - name - Comparison - scope - keyword.operator.comparison,keyword.operator.logical - settings - - foreground - #B83126 - - - - name - String - scope - string - settings - - fontStyle - - foreground - #639300 - - - - name - R Interpolation - scope - string.quoted.double.ruby source.ruby.embedded.source - settings - - foreground - #007E69 - - - - name - Support - scope - support - settings - - fontStyle - - foreground - #104E8B - - - - name - Variable - scope - variable - settings - - foreground - #009ACD - - - - name - Invalid Deprecated - scope - invalid.deprecated - settings - - background - #E8E9E8 - fontStyle - italic underline - foreground - #FD1732 - - - - name - Invalid Illegal - scope - invalid.illegal - settings - - background - #FF060026 - foreground - #FD1224 - - - - name - Embedded Source (Bright) - scope - text source - settings - - background - #77ADE900 - foreground - #7B211A - - - - name - Entity inherited-class - scope - entity.other.inherited-class - settings - - fontStyle - italic - foreground - #005273 - - - - name - String.regexp - scope - string.regexp - settings - - background - #C9D4BE - foreground - #417E00 - - - - name - Support.function - scope - support.function - settings - - fontStyle - - foreground - #005273 - - - - name - Support.constant - scope - support.constant - settings - - fontStyle - - foreground - #CF6A4C - - - - name - j Entity Name Type - scope - entity.name.type - settings - - fontStyle - underline - - - - name - j Cast - scope - meta.cast - settings - - fontStyle - italic - foreground - #676767 - - - - name - Doctype/XML Processing - scope - meta.sgml.html meta.doctype, meta.sgml.html meta.doctype entity, meta.sgml.html meta.doctype string, meta.xml-processing, meta.xml-processing entity, meta.xml-processing string - settings - - foreground - #494949 - - - - name - Meta.tag.all - scope - meta.tag, meta.tag entity - settings - - foreground - #005273 - - - - name - Meta.tag.inline - scope - source entity.name.tag, source entity.other.attribute-name, meta.tag.inline, meta.tag.inline entity - settings - - foreground - #005273 - - - - name - Namespaces - scope - entity.name.tag.namespace, entity.other.attribute-name.namespace - settings - - foreground - #B85423 - - - - name - css tag-name - scope - entity.name.tag.css - settings - - foreground - #B83126 - - - - name - css:pseudo-class - scope - meta.selector.css entity.other.attribute-name.tag.pseudo-class - settings - - foreground - #B12E25 - - - - name - css#id - scope - meta.selector.css entity.other.attribute-name.id,entity.other.attribute-name.id.css - settings - - foreground - #B8002D - - - - name - css.class - scope - meta.selector.css entity.other.attribute-name.class, entity.other.attribute-name.class.css - settings - - foreground - #B8012D - - - - name - css property-name: - scope - support.type.property-name.css, meta.property-name - settings - - foreground - #005273 - - - - name - css @at-rule - scope - meta.preprocessor.at-rule keyword.control.at-rule - settings - - foreground - #8693A5 - - - - name - css property-value; - scope - meta.property-value - settings - - foreground - #417E00 - - - - name - css property-value color - scope - constant.other.color - settings - - foreground - #B8860B - - - - name - css !important / !default - scope - keyword.other.important,keyword.other.default - settings - - foreground - #EE3A8C - - - - name - css additional-constants - scope - meta.property-value support.constant.named-color.css, meta.property-value constant - settings - - foreground - #417E00 - - - - - - name - css constructor.argument - scope - meta.constructor.argument.css - settings - - foreground - #417E00 - - - - name - css constant.numeric - scope - constant.numeric - settings - - foreground - #9A5925 - - - - name - css keyword.unit - scope - keyword.other - settings - - foreground - #9F5E3D - - - - name - css keyword.unit - scope - source.scss support.function.misc - settings - - foreground - #1B76B0 - - - - name - diff.header - scope - meta.diff, meta.diff.header - settings - - background - #82000E - fontStyle - italic - foreground - #F8BEBE - - - - name - diff.deleted - scope - markup.deleted - settings - - background - #420E09 - foreground - #F8F8F8 - - - - name - diff.changed - scope - markup.changed - settings - - background - #4A410D - foreground - #F8F8F8 - - - - name - diff.inserted - scope - markup.inserted - settings - - background - #253B22 - foreground - #F8F8F8 - - - - name - Markup: Italic - scope - markup.italic - settings - - fontStyle - italic - foreground - #CD2626 - - - - name - Markup: Bold - scope - markup.bold - settings - - fontStyle - bold - foreground - #8B1A1A - - - - name - Markup: Underline - scope - markup.underline - settings - - fontStyle - underline - foreground - #E18964 - - - - name - Markup: Quote - scope - markup.quote - settings - - background - #FEE09C12 - fontStyle - italic - foreground - #8B7765 - - - - name - Markup: Heading - scope - markup.heading, markup.heading entity - settings - - background - #BF61330D - fontStyle - - foreground - #B8012D - - - - name - Markup: List - scope - markup.list - settings - - foreground - #8F5B26 - - - - name - Markup: Raw - scope - markup.raw - settings - - background - #B1B3BA08 - fontStyle - - foreground - #578BB3 - - - - name - Markup: Comment - scope - markup comment - settings - - fontStyle - italic - foreground - #F67B37 - - - - name - Markup: Separator - scope - meta.separator - settings - - background - #242424 - foreground - #60A633 - - - - name - Markup: Other - scope - markup.other - settings - - background - #B1B3BA08 - fontStyle - - foreground - #578BB3 - - - - name - Log Entry - scope - meta.line.entry.logfile, meta.line.exit.logfile - settings - - background - #EEEEEE29 - - - - name - Log Entry Error - scope - meta.line.error.logfile - settings - - background - #751012 - - - - name - SCSS Punctuation End Comments - scope - punctuation.definition.end - settings - - background - #DCDCDC8F - fontStyle - - - - - name - -------------------------------- - settings - - - - name - HTML Attribute name - scope - entity.other.attribute-name.html - settings - - foreground - #629F9E - - - - name - JS String - scope - string.quoted.double.js, string.quoted.single.js - settings - - foreground - #79A316 - - - - name - JS Function - scope - entity.name.function.js - settings - - foreground - #488C45 - fontStyle - italic - - - - name - JS Embedded code general - scope - source.js.embedded.html - settings - - foreground - #666 - - - - name - JS Storage Type - scope - storage.type.js - settings - - foreground - #BB3182 - - - - name - JS Support Class - scope - support.class.js - settings - - foreground - #338FD5 - - - - name - JS Control Keyword - scope - keyword.control.js, keyword.operator.js - settings - - foreground - #A99904 - fontStyle - italic - - - - - name - Matching Pairs - scope - entity.name.class - settings - - background - #D7D7A7 - foreground - #616838 - fontStyle - - - - - name - Active Guide - scope - active_guide - settings - - background - #968F96 - fontStyle - - - - - name - Highlight Matching Word - scope - highlight_matching_word - settings - - background - #CBDC2F38 - fontStyle - - - - - uuid - 467560D0-6ACE-4409-82FD-4791420837AC - - diff --git a/tool/update_deps.js b/tool/update_deps.js index c3648d9c..adab36bd 100644 --- a/tool/update_deps.js +++ b/tool/update_deps.js @@ -1,7 +1,7 @@ -var https = require("https"); -var http = require("http"); -var url = require("url"); -var fs = require("fs"); +var https = require("https") + , http = require("http") + , url = require("url") + , fs = require("fs"); var Path = require("path"); var spawn = require("child_process").spawn; @@ -11,7 +11,7 @@ var rootDir = __dirname + "/../lib/ace/"; var deps = { csslint: { path: "mode/css/csslint.js", - url: "https://raw.github.com/stubbornella/csslint/master/release/csslint.js", + url: "https://raw.github.com/stubbornella/csslint/master/release/csslint-node.js", needsFixup: true }, requirejs: { @@ -30,73 +30,49 @@ var deps = { ) } }, - html5: { - path: "mode/html/saxparser.js", - browserify: { - npmModule: "git+https://github.com/aredridel/html5.git#master", - path: "html5/lib/sax/SAXParser.js", - exports: "SAXParser" - }, - fetch: browserify, - needsFixup: true, - postProcess: function(src) { - return src; - } - }, - xquery: { - path: "mode/xquery/xquery_lexer.js", - browserify: { - npmModule: "git+https://github.com/wcandillon/xqlint.git#master", - path: "xqlint/lib/lexers/xquery_lexer.js", - exports: "XQueryLexer" - }, - fetch: browserify, - needsFixup: true, - postProcess: function(src){ - return src; - } - }, - jsoniq: { - path: "mode/xquery/jsoniq_lexer.js", - browserify: { - npmModule: "git+https://github.com/wcandillon/xqlint.git#master", - path: "xqlint/lib/lexers/jsoniq_lexer.js", - exports: "JSONiqLexer" - }, - fetch: browserify, - needsFixup: true, - postProcess: function(src){ - return src; - } - }, - xqlint: { - path: "mode/xquery/xqlint.js", - browserify: { - npmModule: "git+https://github.com/wcandillon/xqlint.git#master", - path: "xqlint/lib/xqlint.js", - exports: "XQLint" - }, - fetch: browserify, - needsFixup: true, - postProcess: function(src){ - return src; - } - }, jshint: { path: "mode/javascript/jshint.js", - browserify: { - npmModule: "git+https://github.com/ajaxorg/jshint.git#master", - path: "jshint/src/jshint.js", - exports: "jshint" + url: "http://jshint.com/get/jshint-2.1.9.js", + fetch: function(_, cb) { + //run("npm install jshint@latest", function() { + var base = Path.join(__dirname, "/node_modules/jshint/") + var path = Path.join(base, "/src/stable/jshint") + run('browserify ' + path + ' -i console-browserify -r jshint', function(err, src) { + src = replaceConsoleBrowserify(src); + var version = JSON.parse(fs.readFileSync(base + "package.json")).version + src = [ "// " + version, + "var JSHINT;", + "(function () {", + "require = null;", + src, + "JSHINT = require('jshint').JSHINT;", + "}());" + ].join("\n") + cb(err, src); + }) + //}); }, - fetch: browserify, needsFixup: true, postProcess: function(src) { + src = src.replace(/(\],|\{)((?:\d+|"\w+"):\[)/g, "$1\n$2") + .replace(/^(\},)(\{[^{}\[\]]*?\}\])/gm, "$1\n$2") + src = src.replace( /"Expected a conditional expression and instead saw an assignment."/g, '"Assignment in conditional expression"' ); + + src = src.replace(/\brequire\(["']|\(require,|\(require\)/g, function(r){ + return r.replace("require", "req"); + }) + src = src.replace(/var defaultMaxListeners = 10;/, function(a) {return a.replace("10", "200")}); + + src = src.replace(/var JSHINT;\s*\(function[\s()]+\{\s*/, "") + .replace(/JSHINT = .*\n\s*\}\(\)\);\s*/, ""); + src += '\n' + + 'function req() {return require.apply(this, arguments)}\n' + + 'module.exports = req("jshint");\n'; return src; } }, @@ -119,26 +95,6 @@ var deps = { }); } }, - vim: { - fetch: function(){ - var rootHref = "https://raw.githubusercontent.com/codemirror/CodeMirror/master/" - var fileMap = {"keymap/vim.js": "keyboard/vim.js", "test/vim_test.js": "keyboard/vim_test.js"}; - async.forEach(Object.keys(fileMap), function(x, next) { - download(rootHref + x, function(e, d) { - d = d.replace(/^\(function.*{[^{}]+^}[^{}]+{/m, "define(function(require, exports, module) {"); - d = d.replace(/^\s*return vimApi;\s*};/gm, " //};") - .replace("var Vim = function() {", "$& return vimApi; } //{") - fs.writeFile(rootDir + fileMap[x], d, next) - }) - }, function() { - console.log("done") - }); - } - }, - liveScript: { - path: "mode/livescript.js", - url: "https://raw.githubusercontent.com/gkz/LiveScript/master/lib/mode-ls.js" - }, coffee: { fetch: function(){ var rootHref = "https://raw.github.com/jashkenas/coffee-script/master/"; @@ -204,24 +160,7 @@ var deps = { }); } } - }, - xmldom: { - fetch: function() { - var rootHref = "https://raw.githubusercontent.com/iDeBugger/xmldom/master/" - var fileMap = { - "sax.js": "mode/xml/sax.js", - "dom-parser.js": "mode/xml/dom-parser.js", - "dom.js": "mode/xml/dom.js" - }; - async.forEach(Object.keys(fileMap), function(x, next) { - download(rootHref + x, function(e, d) { - fs.writeFile(rootDir + fileMap[x], d, next) - }) - }, function() { - console.log("XmlDOM updating done") - }); - } - }, + } }; var download = function(href, callback) { @@ -299,26 +238,23 @@ function unquote(str) { }); } -function browserify(_, cb) { - var br = this.browserify; - var path = Path.join("node_modules", br.path) - run("npm install " + this.browserify.npmModule, function() { - run("browserify " + path + " -s " + br.exports, function(err, src) { - src = src.replace(/^.*return\s*\(function/, "module.exports = (function") - .replace(/\}\);\s*$/, ""); - src = src.replace(/(\],|\{)((?:\d+|"\w+"):\[)/g, "$1\n$2") - .replace(/^(\},)(\{[^{}\[\]]*?\}\])/gm, "$1\n$2") - cb(err, src); - }) - }) +function replaceConsoleBrowserify(str) { + var simpleConsole = function(req,module,exports){ + ["log", "info", "warn", "error", + "time","timeEnd", "trace", "dir", "assert" + ].forEach(function(x) {exports[x] = nop;}); + function nop() {} + } + var m = /"console-browserify":(\d+)/.exec(str); + name = m && m[1]; + if (name) { + str = str.replace( + "{1:[", + "{" + name + ":[" + simpleConsole + ",{}],\n1:[" + ) + } + return str; } -var args = process.argv.slice(2); -args = args.filter(function(x) {return x[0] != "-" }); -if (!args.length) - args = Object.keys(deps); - -args.forEach(function(key) { - getDep(deps[key]) -}); +getDep(deps.jshint) \ No newline at end of file diff --git a/version.js b/version.js index eaf1e5fe..dce117ae 100755 --- a/version.js +++ b/version.js @@ -1,4 +1,4 @@ #!/usr/bin/env node var x; -x = require('./package'); -console.log(x.version) +eval("x= " + require("fs").readFileSync(__dirname + "/package.json")) +console.log(x.version) \ No newline at end of file