From 2636e5de5fa2aa34f28253124bbe3ce91d246fe3 Mon Sep 17 00:00:00 2001 From: takapa Date: Sun, 12 Oct 2014 01:20:27 +0100 Subject: [PATCH 01/53] Improve tooltips Allow tooltips in div element (currently tooltips only allow items in pre element which is tricky to format). Also fix wrapping, remove gradient fill, and introduce a maximum width of 500px by default. --- lib/ace/autocomplete.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js index b4bac72b..f4ef6547 100644 --- a/lib/ace/autocomplete.js +++ b/lib/ace/autocomplete.js @@ -352,12 +352,13 @@ var Autocomplete = function() { this.showDocTooltip = function(item) { if (!this.tooltipNode) { - this.tooltipNode = dom.createElement("pre"); + this.tooltipNode = item.docHTML ? dom.createElement("div") : dom.createElement("pre"); 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; @@ -366,14 +367,15 @@ var Autocomplete = function() { } 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; - + tooltipNode.style.backgroundImage = "none"; + tooltipNode.style.backgroundColor = "#FFFFEE"; if (window.innerWidth - rect.right < 320) { tooltipNode.style.right = window.innerWidth - rect.left + "px"; tooltipNode.style.left = ""; @@ -381,8 +383,11 @@ var Autocomplete = function() { tooltipNode.style.left = (rect.right + 1) + "px"; tooltipNode.style.right = ""; } - // tooltipNode.style.height = rect.height + "px"; tooltipNode.style.display = "block"; + tooltipNode.style.maxWidth = "500px"; + tooltipNode.style.whiteSpace = "normal"; + tooltipNode.style.wordWrap = "normal"; + tooltipNode.style.textAlign = "left"; }; this.hideDocTooltip = function() { From 631695a0e4aaa62baca6902031b91252eb94fc45 Mon Sep 17 00:00:00 2001 From: Adam Jimenez Date: Mon, 20 Oct 2014 17:30:26 +0100 Subject: [PATCH 02/53] Autoindent doesn't always occur Currently autoindent only kicks in as so: ```
|
``` This allows it to also work with: ```
|
``` --- lib/ace/mode/behaviour/xml.js | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js index bd0574c6..eaa570ed 100644 --- a/lib/ace/mode/behaviour/xml.js +++ b/lib/ace/mode/behaviour/xml.js @@ -150,15 +150,33 @@ var XmlBehaviour = function () { if (text == "\n") { var cursor = editor.getCursorPosition(); var line = session.getLine(cursor.row); - var rightChars = line.substring(cursor.column, cursor.column + 2); - if (rightChars == ' Date: Mon, 20 Oct 2014 21:33:23 +0100 Subject: [PATCH 03/53] Responded to suggestions by nightwing Removed style changes (no style changes are part of the PR). Only change now should be that we create a
element instead of a
 element.
---
 lib/ace/autocomplete.js | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js
index f4ef6547..b69743b8 100644
--- a/lib/ace/autocomplete.js
+++ b/lib/ace/autocomplete.js
@@ -352,13 +352,12 @@ var Autocomplete = function() {
     
     this.showDocTooltip = function(item) {
         if (!this.tooltipNode) {
-            this.tooltipNode = item.docHTML ? dom.createElement("div") : dom.createElement("pre");
+            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;
@@ -367,15 +366,14 @@ var Autocomplete = function() {
         } 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;
-        tooltipNode.style.backgroundImage = "none";
-        tooltipNode.style.backgroundColor = "#FFFFEE";
+        
         if (window.innerWidth - rect.right < 320) {
             tooltipNode.style.right = window.innerWidth - rect.left + "px";
             tooltipNode.style.left = "";
@@ -384,10 +382,6 @@ var Autocomplete = function() {
             tooltipNode.style.right = "";
         }
         tooltipNode.style.display = "block";
-        tooltipNode.style.maxWidth = "500px";
-        tooltipNode.style.whiteSpace = "normal";
-        tooltipNode.style.wordWrap = "normal"; 
-        tooltipNode.style.textAlign = "left";
     };
     
     this.hideDocTooltip = function() {

From bf8e9ddf45a04cf3ffa0914aae42aa319268023f Mon Sep 17 00:00:00 2001
From: Adam Jimenez 
Date: Tue, 21 Oct 2014 10:35:34 +0100
Subject: [PATCH 04/53] Fix string tooltips not showing

---
 lib/ace/autocomplete.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js
index b4bac72b..5af6afe4 100644
--- a/lib/ace/autocomplete.js
+++ b/lib/ace/autocomplete.js
@@ -344,7 +344,7 @@ var Autocomplete = function() {
             doc = selected;
         
         if (typeof doc == "string")
-            doc = {tooltipText: doc}
+            doc = {docText: doc}
         if (!doc || !(doc.docHTML || doc.docText))
             return this.hideDocTooltip();
         this.showDocTooltip(doc);

From 7b01a4273e91985c9177f53d238d6b83fe99dc56 Mon Sep 17 00:00:00 2001
From: Adam Jimenez 
Date: Tue, 21 Oct 2014 12:46:29 +0100
Subject: [PATCH 05/53] send completion data to completer callback

---
 lib/ace/autocomplete.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js
index b4bac72b..27f86131 100644
--- a/lib/ace/autocomplete.js
+++ b/lib/ace/autocomplete.js
@@ -177,7 +177,7 @@ var Autocomplete = function() {
             return false;
 
         if (data.completer && data.completer.insertMatch) {
-            data.completer.insertMatch(this.editor);
+            data.completer.insertMatch(this.editor, data);
         } else {
             if (this.completions.filterText) {
                 var ranges = this.editor.selection.getAllRanges();

From 289ada0a2f408a0fd8c67ca20439dbb529db015f Mon Sep 17 00:00:00 2001
From: Adam Jimenez 
Date: Thu, 23 Oct 2014 09:28:42 +0100
Subject: [PATCH 06/53] don't indent after closing tag

---
 lib/ace/mode/behaviour/xml.js | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js
index eaa570ed..0f9d3a66 100644
--- a/lib/ace/mode/behaviour/xml.js
+++ b/lib/ace/mode/behaviour/xml.js
@@ -158,10 +158,22 @@ var XmlBehaviour = function () {
                 while (token && token.type.indexOf('tag-name') === -1) {
                     token = iterator.stepBackward();
                 }
-    
+                
+                if (!token) {
+                    return;
+                }
+                
+                var tag = token.value;
+                
+                //don't indent after closing tag
+                token = iterator.stepBackward();
+                if (token && token.type.indexOf('end-tag') !== -1) {
+                    return;
+                }
+                
                 var single_tags = ['!doctype','area','base','br','hr','input','img','link','meta'];
 
-                if (token && token.value && single_tags.indexOf(token.value) === -1) {
+                if (single_tags.indexOf(tag) === -1) {
                     var nextToken = session.getTokenAt(cursor.row, cursor.column+1);
                     var next_indent = this.$getIndent(line);
                     var indent = next_indent + session.getTabString();
@@ -171,7 +183,7 @@ var XmlBehaviour = function () {
                             text: '\n' + indent + '\n' + next_indent,
                             selection: [1, indent.length, 1, indent.length]
                         };
-                    }else{
+                    } else {
                         return {
                             text: '\n' + indent
                         };

From fd5a6ade03e1475819ed2d6d519b1b3915fecbfa Mon Sep 17 00:00:00 2001
From: nightwing 
Date: Fri, 24 Oct 2014 16:40:53 +0400
Subject: [PATCH 07/53] fix #2183 scrollPastEnd breaks
 vScrollBarAlwaysVisible=false option

---
 lib/ace/virtual_renderer.js | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/lib/ace/virtual_renderer.js b/lib/ace/virtual_renderer.js
index 87c3fa90..820b054d 100644
--- a/lib/ace/virtual_renderer.js
+++ b/lib/ace/virtual_renderer.js
@@ -958,23 +958,24 @@ var VirtualRenderer = function(container, theme) {
             this.scrollBarH.setVisible(horizScroll);
         }
         
-        if (!this.$maxLines && this.$scrollPastEnd) {
-            maxHeight += (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd;
-        }
-        
-        var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
-            size.scrollerHeight - maxHeight < 0);
-        var vScrollChanged = this.$vScroll !== vScroll;
-        if (vScrollChanged) {
-            this.$vScroll = vScroll;
-            this.scrollBarV.setVisible(vScroll);
-        }
+        var scrollPastEnd = !this.$maxLines && this.$scrollPastEnd
+            ? (size.scrollerHeight - this.lineHeight) * this.$scrollPastEnd
+            : 0;
+        maxHeight += scrollPastEnd;
         
         this.session.setScrollTop(Math.max(-this.scrollMargin.top,
             Math.min(this.scrollTop, maxHeight - size.scrollerHeight + this.scrollMargin.bottom)));
 
         this.session.setScrollLeft(Math.max(-this.scrollMargin.left, Math.min(this.scrollLeft, 
             longestLine + 2 * this.$padding - size.scrollerWidth + this.scrollMargin.right)));
+        
+        var vScroll = !hideScrollbars && (this.$vScrollBarAlwaysVisible ||
+            size.scrollerHeight - maxHeight + scrollPastEnd < 0 || this.scrollTop);
+        var vScrollChanged = this.$vScroll !== vScroll;
+        if (vScrollChanged) {
+            this.$vScroll = vScroll;
+            this.scrollBarV.setVisible(vScroll);
+        }
 
         var lineCount = Math.ceil(minHeight / this.lineHeight) - 1;
         var firstRow = Math.max(0, Math.round((this.scrollTop - offset) / this.lineHeight));

From 58d166d647a54d4515c88fc67fef0c611e92d5a6 Mon Sep 17 00:00:00 2001
From: nightwing 
Date: Sat, 25 Oct 2014 02:06:36 +0400
Subject: [PATCH 08/53] do not add extra semicolon in built files

---
 Makefile.dryice.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile.dryice.js b/Makefile.dryice.js
index a6082558..a40549ef 100755
--- a/Makefile.dryice.js
+++ b/Makefile.dryice.js
@@ -502,7 +502,7 @@ function exportAce(ns, modules, requireBase, extModules) {
         if (typeof modules == "string")
             modules = [modules];
             
-        return (text + ";" + template
+        return (text.replace(/;\s*$/, "") + ";" + template
             .toString()
             .replace(/MODULES/g, JSON.stringify(modules))
             .replace(/REQUIRE_NS/g, requireBase)

From 1a70ef15e25df24c9f352cbebae99650989dd9e4 Mon Sep 17 00:00:00 2001
From: nightwing 
Date: Sat, 25 Oct 2014 03:25:44 +0400
Subject: [PATCH 09/53] fix #2190 autocomplete doesn't show tooltip when list
 initially appears

---
 lib/ace/autocomplete.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/ace/autocomplete.js b/lib/ace/autocomplete.js
index 3bb035aa..2544c858 100644
--- a/lib/ace/autocomplete.js
+++ b/lib/ace/autocomplete.js
@@ -67,6 +67,7 @@ var Autocomplete = function() {
             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;

From d068e2f737f46c86cb607a8a297beadfca2415f8 Mon Sep 17 00:00:00 2001
From: coderaiser 
Date: Sat, 25 Oct 2014 18:34:22 +0300
Subject: [PATCH 10/53] feature(version) simplified reading version from
 package.json

---
 version.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/version.js b/version.js
index dce117ae..eaf1e5fe 100755
--- a/version.js
+++ b/version.js
@@ -1,4 +1,4 @@
 #!/usr/bin/env node
 var x;
-eval("x= " + require("fs").readFileSync(__dirname + "/package.json"))
-console.log(x.version)
\ No newline at end of file
+x = require('./package');
+console.log(x.version)

From f3d9c588bd82cf3a19131d437c7fcfb96b434c18 Mon Sep 17 00:00:00 2001
From: coderaiser 
Date: Sat, 25 Oct 2014 18:35:41 +0300
Subject: [PATCH 11/53] feature(package) v1.1.7

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 31a4dec9..9734fc52 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
     "name": "ace",
     "description": "Ajax.org Code Editor is a full featured source code highlighting editor that powers the Cloud9 IDE",
-    "version": "1.0.0",
+    "version": "1.1.7",
     "homepage" : "http://github.com/ajaxorg/ace",
     "engines": {"node": ">= 0.6.0"},
     "author": "Fabian Jakobs ",

From 3ef6bc2097b21f33fded9213fb6e1f32f91bf88a Mon Sep 17 00:00:00 2001
From: nightwing 
Date: Mon, 27 Oct 2014 21:35:51 +0400
Subject: [PATCH 12/53] do not show error for empty json files

---
 lib/ace/mode/json_worker.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/ace/mode/json_worker.js b/lib/ace/mode/json_worker.js
index 9c233d77..57fa1c10 100644
--- a/lib/ace/mode/json_worker.js
+++ b/lib/ace/mode/json_worker.js
@@ -48,7 +48,8 @@ oop.inherits(JsonWorker, Mirror);
         var value = this.doc.getValue();
 
         try {
-            var result = parse(value);
+            if (value)
+                parse(value);
         } catch (e) {
             var pos = this.doc.indexToPosition(e.at-1);
             this.sender.emit("error", {

From b3d0c62a8d6c348c9108cd8025af00c80b5897be Mon Sep 17 00:00:00 2001
From: Adam Jimenez 
Date: Wed, 29 Oct 2014 09:54:16 +0000
Subject: [PATCH 13/53] tidy up autoindent

use voidElements and double quotes.
---
 lib/ace/mode/behaviour/xml.js | 36 +++++++++++++++++------------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js
index 0f9d3a66..708653ab 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
@@ -140,59 +140,57 @@ var XmlBehaviour = function () {
                  return;
 
             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();
-            
-            if (token && token.type.indexOf('tag-close') !== -1) {
+
+            if (token && token.type.indexOf("tag-close") !== -1) {
                 //get tag name
-                while (token && token.type.indexOf('tag-name') === -1) {
+                while (token && token.type.indexOf("tag-name") === -1) {
                     token = iterator.stepBackward();
                 }
-                
+
                 if (!token) {
                     return;
                 }
-                
+
                 var tag = token.value;
-                
+
                 //don't indent after closing tag
                 token = iterator.stepBackward();
-                if (token && token.type.indexOf('end-tag') !== -1) {
+                if (!token || token.type.indexOf("end-tag") !== -1) {
                     return;
                 }
-                
-                var single_tags = ['!doctype','area','base','br','hr','input','img','link','meta'];
 
-                if (single_tags.indexOf(tag) === -1) {
+                if (this.voidElements && !this.voidElements[tag]) {
                     var nextToken = session.getTokenAt(cursor.row, cursor.column+1);
                     var next_indent = this.$getIndent(line);
                     var indent = next_indent + session.getTabString();
-    
-                    if (nextToken && nextToken.value === '
Date: Wed, 29 Oct 2014 10:13:20 +0000
Subject: [PATCH 14/53] autoindent from start of tag

---
 lib/ace/mode/behaviour/xml.js | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js
index 708653ab..1b12f9ea 100644
--- a/lib/ace/mode/behaviour/xml.js
+++ b/lib/ace/mode/behaviour/xml.js
@@ -34,6 +34,7 @@ define(function(require, exports, module) {
 var oop = require("../../lib/oop");
 var Behaviour = require("../behaviour").Behaviour;
 var TokenIterator = require("../../token_iterator").TokenIterator;
+var lang = require("../../lib/lang");
 
 function is(token, type) {
     return token.type.lastIndexOf(type + ".xml") > -1;
@@ -164,6 +165,7 @@ var XmlBehaviour = function () {
                 }
 
                 var tag = token.value;
+                var column = iterator.getCurrentTokenColumn()-1;
 
                 //don't indent after closing tag
                 token = iterator.stepBackward();
@@ -173,7 +175,7 @@ var XmlBehaviour = function () {
 
                 if (this.voidElements && !this.voidElements[tag]) {
                     var nextToken = session.getTokenAt(cursor.row, cursor.column+1);
-                    var next_indent = this.$getIndent(line);
+                    var next_indent = lang.stringRepeat(" ", column);
                     var indent = next_indent + session.getTabString();
 
                     if (nextToken && nextToken.value === "
Date: Wed, 29 Oct 2014 12:08:30 +0000
Subject: [PATCH 15/53] autoindent tweaks

use camelcase and start line indent
---
 lib/ace/mode/behaviour/xml.js | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/lib/ace/mode/behaviour/xml.js b/lib/ace/mode/behaviour/xml.js
index 1b12f9ea..fc46a240 100644
--- a/lib/ace/mode/behaviour/xml.js
+++ b/lib/ace/mode/behaviour/xml.js
@@ -165,7 +165,7 @@ var XmlBehaviour = function () {
                 }
 
                 var tag = token.value;
-                var column = iterator.getCurrentTokenColumn()-1;
+                var row = iterator.getCurrentTokenRow();
 
                 //don't indent after closing tag
                 token = iterator.stepBackward();
@@ -175,12 +175,13 @@ var XmlBehaviour = function () {
 
                 if (this.voidElements && !this.voidElements[tag]) {
                     var nextToken = session.getTokenAt(cursor.row, cursor.column+1);
-                    var next_indent = lang.stringRepeat(" ", column);
-                    var indent = next_indent + session.getTabString();
+                    var line = session.getLine(row);
+                    var nextIndent = this.$getIndent(line);
+                    var indent = nextIndent + session.getTabString();
 
                     if (nextToken && nextToken.value === "
Date: Wed, 29 Oct 2014 13:57:34 +0100
Subject: [PATCH 16/53] Fix typo

---
 api/editor.html | 156 ++++++++++++++++++++++++------------------------
 1 file changed, 78 insertions(+), 78 deletions(-)

diff --git a/api/editor.html b/api/editor.html
index 27c5de90..48df6a68 100644
--- a/api/editor.html
+++ b/api/editor.html
@@ -390,8 +390,8 @@
             

Creates a new Editor object.

-

Arguments

rendererVirtualRenderer

Required. Associated VirtualRenderer that draws everything

-
sessionEditSession

Required. The EditSession to refer to

+

Arguments

rendererVirtualRenderer

Required. Associated VirtualRenderer that draws everything

+
sessionEditSession

Required. The EditSession to refer to

@@ -444,7 +444,7 @@

Emitted whenever the document is changed.

-

Arguments

eObject

Required. Contains a single property, data, which has the delta of changes

+

Arguments

eObject

Required. Contains a single property, data, which has the delta of changes

@@ -471,7 +471,7 @@

Emitted when the selection style changes, via Editor.setSelectionStyle().

-

Arguments

dataObject

Required. Contains one property, data, which indicates the new selection style

+

Arguments

dataObject

Required. Contains one property, data, which indicates the new selection style

@@ -498,7 +498,7 @@

Emitted whenever the EditSession changes.

-

Arguments

eObject

Required. An object with two properties, oldSession and session, that represent the old and new EditSessions.

+

Arguments

eObject

Required. An object with two properties, oldSession and session, that represent the old and new EditSessions.

@@ -525,7 +525,7 @@

Emitted when text is copied.

-

Arguments

textString

Required. The copied text

+

Arguments

textString

Required. The copied text

@@ -577,7 +577,7 @@

Emitted when text is pasted.

-

Arguments

textString

Required. The pasted text

+

Arguments

textString

Required. The pasted text

@@ -610,7 +610,7 @@

Adds the selection and cursor.

-

Arguments

orientedRangeRange

Required. A range containing a cursor

+

Arguments

orientedRangeRange

Required. A range containing a cursor

@@ -920,9 +920,9 @@

Attempts to find needle within the document. For more information on options, see Search.

-

Arguments

needleString

Required. The text to search for (optional)

-
optionsObject

Required. An object defining various search properties

-
animateBoolean

Required. If true animate scrolling

+

Arguments

needleString

Required. The text to search for (optional)

+
optionsObject

Required. An object defining various search properties

+
animateBoolean

Required. If true animate scrolling

@@ -954,9 +954,9 @@

Finds and selects all the occurences of needle.

-

Arguments

TheString

Required. text to find

-
TheObject

Required. search options

-
keepsBoolean

Required.

+

Arguments

TheString

Required. text to find

+
TheObject

Required. search options

+
keepsBoolean

Required.

@@ -983,8 +983,8 @@

Performs another search for needle in the document. For more information on options, see Search.

-

Arguments

optionsObject

Required. search options

-
animateBoolean

Required. If true animate scrolling

+

Arguments

optionsObject

Required. search options

+
animateBoolean

Required. If true animate scrolling

@@ -1011,8 +1011,8 @@

Performs a search for needle backwards. For more information on options, see Search.

-

Arguments

optionsObject

Required. search options

-
animateBoolean

Required. If true animate scrolling

+

Arguments

optionsObject

Required. search options

+
animateBoolean

Required. If true animate scrolling

@@ -1064,8 +1064,8 @@

Executes a command for each selection range.

-

Arguments

cmdString

Required. The command to execute

-
argsString

Required. Any arguments for the command

+

Arguments

cmdString

Required. The command to execute

+
argsString

Required. Any arguments for the command

@@ -1523,8 +1523,8 @@

Works like EditSession.getTokenAt(), except it returns a number.

-

Arguments

rowObject

Required.

-
columnObject

Required.

+

Arguments

rowObject

Required.

+
columnObject

Required.

@@ -1966,9 +1966,9 @@

Moves the cursor to the specified line number, and also into the indiciated column.

-

Arguments

lineNumberNumber

Required. The line number to go to

-
columnNumber

Required. A column number to go to

-
animateBoolean

Required. If true animates scolling

+

Arguments

lineNumberNumber

Required. The line number to go to

+
columnNumber

Required. A column number to go to

+
animateBoolean

Required. If true animates scolling

@@ -2070,7 +2070,7 @@

Inserts text into wherever the cursor is pointing.

-

Arguments

textString

Required. The new text to add

+

Arguments

textString

Required. The new text to add

@@ -2132,7 +2132,7 @@

Indicates if the entire row is currently visible on the screen.

-

Arguments

rowNumber

Required. The row to check

+

Arguments

rowNumber

Required. The row to check

@@ -2164,7 +2164,7 @@

Indicates if the row is currently visible on the screen.

-

Arguments

rowNumber

Required. The row to check

+

Arguments

rowNumber

Required. The row to check

@@ -2191,7 +2191,7 @@

Moves the cursor's row and column to the next matching bracket.

-

Arguments

selectObject

Required.

+

Arguments

selectObject

Required.

@@ -2218,7 +2218,7 @@

If the character before the cursor is a number, this functions changes its value by amount.

-

Arguments

amountNumber

Required. The value to change the numeral by (can be negative to decrease value)

+

Arguments

amountNumber

Required. The value to change the numeral by (can be negative to decrease value)

@@ -2245,8 +2245,8 @@

Moves the cursor to the specified row and column. Note that this does not de-select the current selection.

-

Arguments

rowNumber

Required. The new row number

-
columnNumber

Required. The new column number

+

Arguments

rowNumber

Required. The new row number

+
columnNumber

Required. The new column number

@@ -2273,7 +2273,7 @@

Moves the cursor to the position indicated by pos.row and pos.column.

-

Arguments

posObject

Required. An object with two properties, row and column

+

Arguments

posObject

Required. An object with two properties, row and column

@@ -2384,7 +2384,7 @@

Moves the cursor down in the document the specified number of times. Note that this does de-select the current selection.

-

Arguments

timesNumber

Required. The number of times to change navigation

+

Arguments

timesNumber

Required. The number of times to change navigation

@@ -2461,7 +2461,7 @@

Moves the cursor left in the document the specified number of times. Note that this does de-select the current selection.

-

Arguments

timesNumber

Required. The number of times to change navigation

+

Arguments

timesNumber

Required. The number of times to change navigation

@@ -2538,7 +2538,7 @@

Moves the cursor right in the document the specified number of times. Note that this does de-select the current selection.

-

Arguments

timesNumber

Required. The number of times to change navigation

+

Arguments

timesNumber

Required. The number of times to change navigation

@@ -2565,8 +2565,8 @@

Moves the cursor to the specified row and column. Note that this does de-select the current selection.

-

Arguments

rowNumber

Required. The new row number

-
columnNumber

Required. The new column number

+

Arguments

rowNumber

Required. The new row number

+
columnNumber

Required. The new column number

@@ -2593,7 +2593,7 @@

Moves the cursor up in the document the specified number of times. Note that this does de-select the current selection.

-

Arguments

timesNumber

Required. The number of times to change navigation

+

Arguments

timesNumber

Required. The number of times to change navigation

@@ -3105,7 +3105,7 @@

Called whenever a text "paste" happens.

-

Arguments

textString

Required. The pasted text

+

Arguments

textString

Required. The pasted text

@@ -3277,7 +3277,7 @@

Removes words of text from the editor. A "word" is defined as a string of characters bookended by whitespace.

-

Arguments

dirString

Required. The direction of the deletion to occur, either "left" or "right"

+

Arguments

dirString

Required. The direction of the deletion to occur, either "left" or "right"

@@ -3329,7 +3329,7 @@

Removes the selection marker.

-

Arguments

TheRange

Required. selection range added with addSelectionMarker().

+

Arguments

TheRange

Required. selection range added with addSelectionMarker().

@@ -3456,8 +3456,8 @@

Replaces the first occurance of options.needle with the value in replacement.

-

Arguments

replacementString

Required. The text to replace with

-
optionsObject

Required. The Search options to use

+

Arguments

replacementString

Required. The text to replace with

+
optionsObject

Required. The Search options to use

@@ -3484,8 +3484,8 @@

Replaces all occurances of options.needle with the value in replacement.

-

Arguments

replacementString

Required. The text to replace with

-
optionsObject

Required. The Search options to use

+

Arguments

replacementString

Required. The text to replace with

+
optionsObject

Required. The Search options to use

@@ -3512,7 +3512,7 @@

Triggers a resize of the editor.

-

Arguments

forceBoolean

Required. If true, recomputes the size, even if the height and width haven't changed

+

Arguments

forceBoolean

Required. If true, recomputes the size, even if the height and width haven't changed

@@ -3613,10 +3613,10 @@

Scrolls to a line. If center is true, it puts the line in middle of screen (or attempts to).

-

Arguments

lineNumber

Required. The line to scroll to

-
centerBoolean

Required. If true

-
animateBoolean

Required. If true animates scrolling

-
callbackFunction

Required. Function to be called when the animation has finished

+

Arguments

lineNumber

Required. The line to scroll to

+
centerBoolean

Required. If true

+
animateBoolean

Required. If true animates scrolling

+
callbackFunction

Required. Function to be called when the animation has finished

@@ -3643,7 +3643,7 @@

Moves the editor to the specified row.

-

Arguments

rowObject

Required.

+

Arguments

rowObject

Required.

@@ -3695,8 +3695,8 @@

Finds the next occurence of text in an active selection and adds it to the selections.

-

Arguments

dirNumber

Required. The direction of lines to select: -1 for up, 1 for down

-
skipBoolean

Required. If true, removes the active selection range

+

Arguments

dirNumber

Required. The direction of lines to select: -1 for up, 1 for down

+
skipBoolean

Required. If true, removes the active selection range

@@ -3723,8 +3723,8 @@

Adds a cursor above or below the active cursor.

-

Arguments

dirNumber

Required. The direction of lines to select: -1 for up, 1 for down

-
skipBoolean

Required. If true, removes the active selection range

+

Arguments

dirNumber

Required. The direction of lines to select: -1 for up, 1 for down

+
skipBoolean

Required. If true, removes the active selection range

@@ -3825,7 +3825,7 @@

Specifies whether to use behaviors or not. "Behaviors" in this case is the auto-pairing of special characters, like quotation marks, parenthesis, or brackets.

-

Arguments

enabledBoolean

Required. Enables or disables behaviors

+

Arguments

enabledBoolean

Required. Enables or disables behaviors

@@ -3876,7 +3876,7 @@

Sets the delay (in milliseconds) of the mouse drag.

-

Arguments

dragDelayNumber

Required. A value indicating the new delay

+

Arguments

dragDelayNumber

Required. A value indicating the new delay

@@ -3927,7 +3927,7 @@

Set a new font size (in pixels) for the editor text.

-

Arguments

sizeNumber

Required. A font size

+

Arguments

sizeNumber

Required. A font size

@@ -3954,7 +3954,7 @@

Determines whether or not the current line should be highlighted.

-

Arguments

shouldHighlightBoolean

Required. Set to true to highlight the current line

+

Arguments

shouldHighlightBoolean

Required. Set to true to highlight the current line

@@ -4005,7 +4005,7 @@

Determines if the currently selected word should be highlighted.

-

Arguments

shouldHighlightBoolean

Required. Set to true to highlight the currently selected word

+

Arguments

shouldHighlightBoolean

Required. Set to true to highlight the currently selected word

@@ -4032,7 +4032,7 @@

Sets a new key handler, such as "vim" or "windows".

-

Arguments

keyboardHandlerString

Required. The new key handler

+

Arguments

keyboardHandlerString

Required. The new key handler

@@ -4059,7 +4059,7 @@

Pass in true to enable overwrites in your session, or false to disable. If overwrites is enabled, any text you enter will type over any text after it. If the value of overwrite changes, this function also emites the changeOverwrite event.

-

Arguments

overwriteBoolean

Required. Defines wheter or not to set overwrites

+

Arguments

overwriteBoolean

Required. Defines wheter or not to set overwrites

@@ -4086,7 +4086,7 @@

Sets the column defining where the print margin should be.

-

Arguments

showPrintMarginNumber

Required. Specifies the new print margin

+

Arguments

showPrintMarginNumber

Required. Specifies the new print margin

@@ -4113,7 +4113,7 @@

If readOnly is true, then the editor is set to read-only mode, and none of the content can change.

-

Arguments

readOnlyBoolean

Required. Specifies whether the editor can be modified or not

+

Arguments

readOnlyBoolean

Required. Specifies whether the editor can be modified or not

@@ -4140,7 +4140,7 @@

Sets how fast the mouse scrolling should do.

-

Arguments

speedNumber

Required. A value indicating the new speed (in milliseconds)

+

Arguments

speedNumber

Required. A value indicating the new speed (in milliseconds)

@@ -4170,7 +4170,7 @@ although this code change in the future.

This function also emits the 'changeSelectionStyle' event.

-

Arguments

styleString

Required. The new selection style

+

Arguments

styleString

Required. The new selection style

@@ -4197,7 +4197,7 @@ although this code change in the future.

Sets a new editsession to use. This method also emits the 'changeSession' event.

-

Arguments

sessionEditSession

Required. The new session to use

+

Arguments

sessionEditSession

Required. The new session to use

@@ -4224,7 +4224,7 @@ although this code change in the future.

Indicates whether the fold widgets are shown or not.

-

Arguments

showBoolean

Required. Specifies whether the fold widgets are shown

+

Arguments

showBoolean

Required. Specifies whether the fold widgets are shown

@@ -4251,7 +4251,7 @@ although this code change in the future.

If showInvisibles is set to true, invisible characters—like spaces or new lines—are show in the editor.

-

Arguments

showInvisiblesBoolean

Required. Specifies whether or not to show invisible characters

+

Arguments

showInvisiblesBoolean

Required. Specifies whether or not to show invisible characters

@@ -4278,7 +4278,7 @@ although this code change in the future.

If showPrintMargin is set to true, the print margin is shown in the editor.

-

Arguments

showPrintMarginBoolean

Required. Specifies whether or not to show the print margin

+

Arguments

showPrintMarginBoolean

Required. Specifies whether or not to show the print margin

@@ -4305,7 +4305,7 @@ although this code change in the future.

Adds a new class, style, to the editor.

-

Arguments

styleString

Required. A class name

+

Arguments

styleString

Required. A class name

@@ -4332,7 +4332,7 @@ although this code change in the future.

Sets a new theme for the editor. theme should exist, and be a directory path, like ace/theme/textmate.

-

Arguments

themeString

Required. The path to a theme

+

Arguments

themeString

Required. The path to a theme

@@ -4364,8 +4364,8 @@ although this code change in the future.

Sets the current document to val.

-

Arguments

valString

Required. The new value to set for the document

-
cursorPosNumber

Required. Where to set the new value. undefined or 0 is selectAll, -1 is at the document start, and 1 is at the end

+

Arguments

valString

Required. The new value to set for the document

+
cursorPosNumber

Required. Where to set the new value. undefined or 0 is selectAll, -1 is at the document start, and 1 is at the end

@@ -4394,7 +4394,7 @@ when such a character is typed in.

Specifies whether to use wrapping behaviors or not, i.e. automatically wrapping the selection with characters such as brackets when such a character is typed in.

-

Arguments

enabledBoolean

Required. Enables or disables wrapping behaviors

+

Arguments

enabledBoolean

Required. Enables or disables wrapping behaviors

@@ -4595,7 +4595,7 @@ when such a character is typed in.

Transposes the selected ranges.

-

Arguments

dirNumber

Required. The direction to rotate selections

+

Arguments

dirNumber

Required. The direction to rotate selections

@@ -4647,7 +4647,7 @@ when such a character is typed in.

Removes the class style from the editor.

-

Arguments

styleObject

Required.

+

Arguments

styleObject

Required.

From 292d92ab8cc8c43fd18a0f114db4b1e090d656af Mon Sep 17 00:00:00 2001 From: Bolutife Ogunsola Date: Wed, 29 Oct 2014 14:17:01 +0100 Subject: [PATCH 17/53] Update documentation to reflect change introduced in 9253fffb9f --- api/editor.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/editor.html b/api/editor.html index 48df6a68..6ffe4369 100644 --- a/api/editor.html +++ b/api/editor.html @@ -564,7 +564,7 @@
    • -
    • Editor.on("paste", function(String text))
    • +
    • Editor.on("paste", function(Object e))
    @@ -577,7 +577,7 @@

    Emitted when text is pasted.

    -

    Arguments

    textString

    Required. The pasted text

    +

    Arguments

    eObject

    Required. An object which contains one property, text, that represents the text to be pasted. Editing this property will alter the text that is pasted.

    From b204cd72366c343435616445b7aa6e5c66b529c1 Mon Sep 17 00:00:00 2001 From: Adam Jimenez Date: Wed, 29 Oct 2014 17:01:41 +0000 Subject: [PATCH 18/53] use mode delegates in PHP fixes #2197 --- lib/ace/mode/php.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index beeefda7..3bb2e6a5 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.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 @@ -41,8 +41,11 @@ var WorkerClient = require("../worker/worker_client").WorkerClient; var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var unicode = require("../unicode"); +var HtmlMode = require("./html").Mode; +var JavaScriptMode = require("./javascript").Mode; +var CssMode = require("./css").Mode; -var Mode = function(opts) { +var PhpMode = function(opts) { this.inlinePhp = opts && opts.inline; var HighlightRules = this.inlinePhp ? PhpLangHighlightRules : PhpHighlightRules; this.HighlightRules = HighlightRules; @@ -50,7 +53,18 @@ var Mode = function(opts) { this.$behaviour = new CstyleBehaviour(); this.foldingRules = new CStyleFoldMode(); }; -oop.inherits(Mode, TextMode); +oop.inherits(PhpMode, TextMode); + +var Mode = function() { + HtmlMode.call(this); + this.HighlightRules = PhpHighlightRules; + this.createModeDelegates({ + "js-": JavaScriptMode, + "css-": CssMode, + "php-": PhpMode + }); +}; +oop.inherits(Mode, HtmlMode); (function() { @@ -60,7 +74,7 @@ oop.inherits(Mode, TextMode); + unicode.packages.Nd + unicode.packages.Pc + "\_]+", "g" ); - + this.nonTokenRe = new RegExp("^(?:[^" + unicode.packages.L + unicode.packages.Mn + unicode.packages.Mc @@ -68,7 +82,7 @@ oop.inherits(Mode, TextMode); + unicode.packages.Pc + "\_]|\s])+", "g" ); - + this.lineCommentStart = ["//", "#"]; this.blockComment = {start: "/*", end: "*/"}; @@ -106,17 +120,19 @@ oop.inherits(Mode, TextMode); }; this.checkOutdent = function(state, line, input) { - return this.$outdent.checkOutdent(line, input); + if (this.$outdent) + return this.$outdent.checkOutdent(line, input); }; this.autoOutdent = function(state, doc, row) { - this.$outdent.autoOutdent(doc, row); + if (this.$outdent) + this.$outdent.autoOutdent(doc, row); }; this.createWorker = function(session) { var worker = new WorkerClient(["ace"], "ace/mode/php_worker", "PhpWorker"); worker.attachToDocument(session.getDocument()); - + if (this.inlinePhp) worker.call("setOptions", [{inline: true}]); From f121ca93ffc8be1bc7c51596c554ad47374337bf Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 29 Oct 2014 23:18:09 +0400 Subject: [PATCH 19/53] update comment too --- lib/ace/editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 20a04987..9d911410 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -888,7 +888,7 @@ var Editor = function(renderer, session) { /** * Emitted when text is pasted. * @event paste - * @param {String} text The pasted text + * @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. * * **/ From c0b37c1ac2a2319b643a89f8d2497370ad0ece04 Mon Sep 17 00:00:00 2001 From: Randall Koutnik Date: Wed, 29 Oct 2014 17:09:09 -0700 Subject: [PATCH 20/53] Add COPY as a Docker command to be highlighted --- lib/ace/mode/dockerfile_highlight_rules.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ace/mode/dockerfile_highlight_rules.js b/lib/ace/mode/dockerfile_highlight_rules.js index 3ea8c088..c94ed650 100644 --- a/lib/ace/mode/dockerfile_highlight_rules.js +++ b/lib/ace/mode/dockerfile_highlight_rules.js @@ -42,7 +42,7 @@ var DockerfileHighlightRules = function() { 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)\\b)", + regex: "(?:^(?:FROM|MAINTAINER|RUN|CMD|EXPOSE|ENV|ADD|ENTRYPOINT|VOLUME|USER|WORKDIR|ONBUILD|COPY)\\b)", caseInsensitive: true }); break; From 2bd2e3736795387597f28cb7ba017663113e6889 Mon Sep 17 00:00:00 2001 From: Adam Jimenez Date: Thu, 30 Oct 2014 01:52:38 +0000 Subject: [PATCH 21/53] fix php indentation --- lib/ace/mode/php.js | 88 +++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index 3bb2e6a5..101cc3c0 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.js @@ -55,6 +55,51 @@ var PhpMode = function(opts) { }; oop.inherits(PhpMode, TextMode); +(function() { + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[\:]\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState != "doc-start") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.$id = "ace/mode/php-inline"; +}).call(PhpMode.prototype); + var Mode = function() { HtmlMode.call(this); this.HighlightRules = PhpHighlightRules; @@ -86,49 +131,6 @@ oop.inherits(Mode, HtmlMode); this.lineCommentStart = ["//", "#"]; this.blockComment = {start: "/*", end: "*/"}; - this.getNextLineIndent = function(state, line, tab) { - var indent = this.$getIndent(line); - - var tokenizedLine = this.getTokenizer().getLineTokens(line, state); - var tokens = tokenizedLine.tokens; - var endState = tokenizedLine.state; - - - if (tokens.length && tokens[tokens.length-1].type == "comment") { - return indent; - } - - if (state == "php-start") { - var match = line.match(/^.*[\{\(\[\:]\s*$/); - if (match) { - indent += tab; - } - } else if (state == "php-doc-start") { - if (endState != "php-doc-start") { - return ""; - } - var match = line.match(/^\s*(\/?)\*/); - if (match) { - if (match[1]) { - indent += " "; - } - indent += "* "; - } - } - - return indent; - }; - - this.checkOutdent = function(state, line, input) { - if (this.$outdent) - return this.$outdent.checkOutdent(line, input); - }; - - this.autoOutdent = function(state, doc, row) { - if (this.$outdent) - this.$outdent.autoOutdent(doc, row); - }; - this.createWorker = function(session) { var worker = new WorkerClient(["ace"], "ace/mode/php_worker", "PhpWorker"); worker.attachToDocument(session.getDocument()); From 366675a7a74ed341b9313b52e6b12f19aa0be510 Mon Sep 17 00:00:00 2001 From: nightwing Date: Fri, 31 Oct 2014 15:08:44 +0400 Subject: [PATCH 22/53] fix inline php mode --- lib/ace/mode/php.js | 10 ++++--- lib/ace/mode/php_test.js | 65 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 lib/ace/mode/php_test.js diff --git a/lib/ace/mode/php.js b/lib/ace/mode/php.js index 101cc3c0..a44e79c6 100644 --- a/lib/ace/mode/php.js +++ b/lib/ace/mode/php.js @@ -46,9 +46,7 @@ var JavaScriptMode = require("./javascript").Mode; var CssMode = require("./css").Mode; var PhpMode = function(opts) { - this.inlinePhp = opts && opts.inline; - var HighlightRules = this.inlinePhp ? PhpLangHighlightRules : PhpHighlightRules; - this.HighlightRules = HighlightRules; + this.HighlightRules = PhpLangHighlightRules; this.$outdent = new MatchingBraceOutdent(); this.$behaviour = new CstyleBehaviour(); this.foldingRules = new CStyleFoldMode(); @@ -100,7 +98,11 @@ oop.inherits(PhpMode, TextMode); this.$id = "ace/mode/php-inline"; }).call(PhpMode.prototype); -var Mode = function() { +var Mode = function(opts) { + if (opts && opts.inline) { + PhpMode.call(this); + return; + } HtmlMode.call(this); this.HighlightRules = PhpHighlightRules; this.createModeDelegates({ diff --git a/lib/ace/mode/php_test.js b/lib/ace/mode/php_test.js new file mode 100644 index 00000000..9e86a304 --- /dev/null +++ b/lib/ace/mode/php_test.js @@ -0,0 +1,65 @@ +/* ***** 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"); +} + +define(function(require, exports, module) { +"use strict"; + +var EditSession = require("../edit_session").EditSession; +var Tokenizer = require("../tokenizer").Tokenizer; +var Mode = require("./php").Mode; +var assert = require("../test/assertions"); + +module.exports = { + "test: inline mode" : function() { + var mode = new Mode(); + var tokenizer = mode.getTokenizer(); + var tokens = tokenizer.getLineTokens("'juhu kinners' ?> html html Date: Sat, 1 Nov 2014 18:15:00 +0400 Subject: [PATCH 23/53] support nested comments in rust mode --- lib/ace/mode/rust_highlight_rules.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ace/mode/rust_highlight_rules.js b/lib/ace/mode/rust_highlight_rules.js index 1a7d38a6..422e8e80 100644 --- a/lib/ace/mode/rust_highlight_rules.js +++ b/lib/ace/mode/rust_highlight_rules.js @@ -127,10 +127,14 @@ var RustHighlightRules = function() { regex: '$', next: 'pop' }, { defaultToken: 'comment.line.double-dash.source.rust' } ] }, - { token: 'comment.block.source.rust', + { token: 'comment.start.block.source.rust', regex: '/\\*', + stateName: 'comment', push: - [ { token: 'comment.block.source.rust', + [ { token: 'comment.start.block.source.rust', + regex: '/\\*', + push: 'comment' }, + { token: 'comment.end.block.source.rust', regex: '\\*/', next: 'pop' }, { defaultToken: 'comment.block.source.rust' } ] } ], From 5b3bbba54e07a4c14b6bb8f34c1ce55eea0e58b2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 1 Nov 2014 19:27:40 +0400 Subject: [PATCH 24/53] fix xquery mode breaking autocompletion and add tests --- lib/ace/ext/language_tools.js | 3 + lib/ace/mode/_test/highlight_rules_test.js | 9 +- lib/ace/mode/_test/tokens_eiffel.json | 141 ++++++++++ lib/ace/mode/_test/tokens_elm.json | 198 ++++++++++++++ lib/ace/mode/_test/tokens_gcode.json | 296 +++++++++++++++++++++ lib/ace/mode/_test/tokens_io.json | 49 ++++ lib/ace/mode/_test/tokens_jsoniq.json | 4 + lib/ace/mode/_test/tokens_matlab.json | 88 +++++- lib/ace/mode/_test/tokens_xquery.json | 44 +++ lib/ace/mode/jsoniq.js | 7 +- lib/ace/mode/xquery.js | 7 +- lib/ace/snippets/dockerfile.js | 7 + lib/ace/snippets/dockerfile.snippets | 0 lib/ace/snippets/dummy.js | 7 + lib/ace/snippets/dummy_syntax.js | 7 + lib/ace/snippets/eiffel.js | 7 + lib/ace/snippets/eiffel.snippets | 0 lib/ace/snippets/elm.js | 7 + lib/ace/snippets/elm.snippets | 0 lib/ace/snippets/io.snippets | 0 lib/ace/snippets/vala.snippets | 0 21 files changed, 871 insertions(+), 10 deletions(-) create mode 100644 lib/ace/mode/_test/tokens_eiffel.json create mode 100644 lib/ace/mode/_test/tokens_elm.json create mode 100644 lib/ace/mode/_test/tokens_gcode.json create mode 100644 lib/ace/mode/_test/tokens_io.json create mode 100644 lib/ace/mode/_test/tokens_jsoniq.json create mode 100644 lib/ace/mode/_test/tokens_xquery.json create mode 100644 lib/ace/snippets/dockerfile.js create mode 100644 lib/ace/snippets/dockerfile.snippets create mode 100644 lib/ace/snippets/dummy.js create mode 100644 lib/ace/snippets/dummy_syntax.js create mode 100644 lib/ace/snippets/eiffel.js create mode 100644 lib/ace/snippets/eiffel.snippets create mode 100644 lib/ace/snippets/elm.js create mode 100644 lib/ace/snippets/elm.snippets create mode 100644 lib/ace/snippets/io.snippets create mode 100644 lib/ace/snippets/vala.snippets diff --git a/lib/ace/ext/language_tools.js b/lib/ace/ext/language_tools.js index 4687efd5..12fcf5b2 100644 --- a/lib/ace/ext/language_tools.js +++ b/lib/ace/ext/language_tools.js @@ -40,6 +40,9 @@ 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); diff --git a/lib/ace/mode/_test/highlight_rules_test.js b/lib/ace/mode/_test/highlight_rules_test.js index 647ca3c3..e0244abc 100644 --- a/lib/ace/mode/_test/highlight_rules_test.js +++ b/lib/ace/mode/_test/highlight_rules_test.js @@ -58,7 +58,8 @@ function checkModes() { } function generateTestData() { - var docs = jsFileList(cwd + root); + var docRoot = root + "/demo/kitchen-sink/docs"; + var docs = fs.readdirSync(docRoot); var specialDocs = fs.readdirSync(cwd); var modes = modeList(); @@ -79,10 +80,12 @@ function generateTestData() { var filePath = "text_" + modeName + ".txt"; if (specialDocs.indexOf(filePath) == -1) { - filePath = root + "/" + docName; + filePath = docRoot + "/" + docName; + } else { + filePath = cwd + filePath; } - var text = fs.readFileSync(cwd + filePath, "utf8"); + var text = fs.readFileSync(filePath, "utf8"); try { var Mode = require("../" + modeName).Mode; } catch(e) { diff --git a/lib/ace/mode/_test/tokens_eiffel.json b/lib/ace/mode/_test/tokens_eiffel.json new file mode 100644 index 00000000..344dbc62 --- /dev/null +++ b/lib/ace/mode/_test/tokens_eiffel.json @@ -0,0 +1,141 @@ +[[ + "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_elm.json b/lib/ace/mode/_test/tokens_elm.json new file mode 100644 index 00000000..b39de92f --- /dev/null +++ b/lib/ace/mode/_test/tokens_elm.json @@ -0,0 +1,198 @@ +[[ + "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_gcode.json b/lib/ace/mode/_test/tokens_gcode.json new file mode 100644 index 00000000..d6227473 --- /dev/null +++ b/lib/ace/mode/_test/tokens_gcode.json @@ -0,0 +1,296 @@ +[[ + "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_io.json b/lib/ace/mode/_test/tokens_io.json new file mode 100644 index 00000000..b83a675a --- /dev/null +++ b/lib/ace/mode/_test/tokens_io.json @@ -0,0 +1,49 @@ +[[ + "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_jsoniq.json b/lib/ace/mode/_test/tokens_jsoniq.json new file mode 100644 index 00000000..0f4ee6e9 --- /dev/null +++ b/lib/ace/mode/_test/tokens_jsoniq.json @@ -0,0 +1,4 @@ +[[ + "[\"start\"]", + ["support.function","TODO"] +]] \ No newline at end of file diff --git a/lib/ace/mode/_test/tokens_matlab.json b/lib/ace/mode/_test/tokens_matlab.json index 9909eadd..6b4a8567 100644 --- a/lib/ace/mode/_test/tokens_matlab.json +++ b/lib/ace/mode/_test/tokens_matlab.json @@ -1,4 +1,90 @@ [[ + ["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", - ["identifier","TODO"] + ["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_xquery.json b/lib/ace/mode/_test/tokens_xquery.json new file mode 100644 index 00000000..aaf9ab9b --- /dev/null +++ b/lib/ace/mode/_test/tokens_xquery.json @@ -0,0 +1,44 @@ +[[ + "[\"start\"]", + ["keyword","xquery"], + ["text"," "], + ["keyword","version"], + ["text"," "], + ["string","\""], + ["string","1.0"], + ["string","\""], + ["text",";"] +],[ + "[\"start\"]" +],[ + "[\"start\"]", + ["keyword","let"], + ["text"," "], + ["variable","$message"], + ["text"," "], + ["keyword.operator",":="], + ["text"," "], + ["string","\""], + ["string","Hello World!"], + ["string","\""] +],[ + "[\"start\",\"StartTag\",\"TagContent\"]", + ["keyword","return"], + ["text"," "], + ["meta.tag",""] +],[ + "[\"start\",\"StartTag\",\"TagContent\"]", + ["text"," "], + ["meta.tag",""], + ["text","{"], + ["variable","$message"], + ["text","}"], + ["meta.tag",""] +],[ + "[\"start\"]", + ["meta.tag",""] +],[ + "[\"start\"]" +]] \ No newline at end of file diff --git a/lib/ace/mode/jsoniq.js b/lib/ace/mode/jsoniq.js index 6f10d2d3..64dc9541 100644 --- a/lib/ace/mode/jsoniq.js +++ b/lib/ace/mode/jsoniq.js @@ -39,7 +39,6 @@ var Range = require("../range").Range; var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Anchor = require("../anchor").Anchor; -var LanguageTools = require("../ext/language_tools"); var Mode = function() { this.$tokenizer = new JSONiqLexer(); @@ -52,14 +51,16 @@ oop.inherits(Mode, TextMode); (function() { - LanguageTools.addCompleter({ + this.completer = { getCompletions: function(editor, session, pos, prefix, callback) { + if (!session.$worker) + return callback(); session.$worker.emit("complete", { data: { pos: pos, prefix: prefix } }); session.$worker.on("complete", function(e){ callback(null, e.data); }); } - }); + }; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); diff --git a/lib/ace/mode/xquery.js b/lib/ace/mode/xquery.js index b93d61d2..024a5c6a 100644 --- a/lib/ace/mode/xquery.js +++ b/lib/ace/mode/xquery.js @@ -39,7 +39,6 @@ var Range = require("../range").Range; var XQueryBehaviour = require("./behaviour/xquery").XQueryBehaviour; var CStyleFoldMode = require("./folding/cstyle").FoldMode; var Anchor = require("../anchor").Anchor; -var LanguageTools = require("../ext/language_tools"); var Mode = function() { this.$tokenizer = new XQueryLexer(); @@ -51,14 +50,16 @@ oop.inherits(Mode, TextMode); (function() { - LanguageTools.addCompleter({ + this.completer = { getCompletions: function(editor, session, pos, prefix, callback) { + if (!session.$worker) + return callback(); session.$worker.emit("complete", { data: { pos: pos, prefix: prefix } }); session.$worker.on("complete", function(e){ callback(null, e.data); }); } - }); + }; this.getNextLineIndent = function(state, line, tab) { var indent = this.$getIndent(line); diff --git a/lib/ace/snippets/dockerfile.js b/lib/ace/snippets/dockerfile.js new file mode 100644 index 00000000..057347fb --- /dev/null +++ b/lib/ace/snippets/dockerfile.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./dockerfile.snippets"); +exports.scope = "dockerfile"; + +}); diff --git a/lib/ace/snippets/dockerfile.snippets b/lib/ace/snippets/dockerfile.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/dummy.js b/lib/ace/snippets/dummy.js new file mode 100644 index 00000000..359d9103 --- /dev/null +++ b/lib/ace/snippets/dummy.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./.snippets"); +exports.scope = ""; + +}); diff --git a/lib/ace/snippets/dummy_syntax.js b/lib/ace/snippets/dummy_syntax.js new file mode 100644 index 00000000..359d9103 --- /dev/null +++ b/lib/ace/snippets/dummy_syntax.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./.snippets"); +exports.scope = ""; + +}); diff --git a/lib/ace/snippets/eiffel.js b/lib/ace/snippets/eiffel.js new file mode 100644 index 00000000..04f4c5a9 --- /dev/null +++ b/lib/ace/snippets/eiffel.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./eiffel.snippets"); +exports.scope = "eiffel"; + +}); diff --git a/lib/ace/snippets/eiffel.snippets b/lib/ace/snippets/eiffel.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/elm.js b/lib/ace/snippets/elm.js new file mode 100644 index 00000000..44f18c11 --- /dev/null +++ b/lib/ace/snippets/elm.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./elm.snippets"); +exports.scope = "elm"; + +}); diff --git a/lib/ace/snippets/elm.snippets b/lib/ace/snippets/elm.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/io.snippets b/lib/ace/snippets/io.snippets new file mode 100644 index 00000000..e69de29b diff --git a/lib/ace/snippets/vala.snippets b/lib/ace/snippets/vala.snippets new file mode 100644 index 00000000..e69de29b From ca9bc7a97a00f15b421a08d2abe3c87e5eac9df3 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 1 Nov 2014 21:44:53 +0400 Subject: [PATCH 25/53] improve highlighting of ruby strings --- lib/ace/mode/ruby_highlight_rules.js | 68 ++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/lib/ace/mode/ruby_highlight_rules.js b/lib/ace/mode/ruby_highlight_rules.js index 13dcd1b2..a1cb12f9 100644 --- a/lib/ace/mode/ruby_highlight_rules.js +++ b/lib/ace/mode/ruby_highlight_rules.js @@ -141,9 +141,71 @@ var RubyHighlightRules = function() { regex : "[/](?:(?:\\[(?:\\\\]|[^\\]])+\\])|(?:\\\\/|[^\\]/]))*[/]\\w*\\s*(?=[).,;]|$)" }, - qString, - qqString, - tString, + [{ + regex: "[{}]", onMatch: function(val, state, stack) { + this.next = val == "{" ? this.nextState : ""; + if (val == "{" && stack.length) { + stack.unshift("start", state); + return "paren.lparen"; + } + if (val == "}" && stack.length) { + stack.shift(); + this.next = stack.shift(); + if (this.next.indexOf("string") != -1) + return "paren.end"; + } + return val == "{" ? "paren.lparen" : "paren.rparen"; + }, + nextState: "start" + }, { + token : "string.start", + regex : /"/, + push : [{ + token : "constant.language.escape", + regex : /\\(?:[nsrtvfbae'"\\]|c.|C-.|M-.(?:\\C-.)?|[0-7]{3}|x[\da-fA-F]{2}|u[\da-fA-F]{4})/ + }, { + token : "paren.start", + regex : /\#{/, + push : "start" + }, { + token : "string.end", + regex : /"/, + next : "pop" + }, { + defaultToken: "string" + }] + }, { + token : "string.start", + regex : /`/, + push : [{ + token : "constant.language.escape", + regex : /\\(?:[nsrtvfbae'"\\]|c.|C-.|M-.(?:\\C-.)?|[0-7]{3}|x[\da-fA-F]{2}|u[\da-fA-F]{4})/ + }, { + token : "paren.start", + regex : /\#{/, + push : "start" + }, { + token : "string.end", + regex : /`/, + next : "pop" + }, { + defaultToken: "string" + }] + }, { + token : "string.start", + regex : /'/, + push : [{ + token : "constant.language.escape", + regex : /\\['\\]/ + }, { + token : "string.end", + regex : /'/, + next : "pop" + }, { + defaultToken: "string" + }] + }], + // TODO: add support for %[QqxWwrs][{[(] { token : "text", // namespaces aren't symbols From 4da689e71b52825332fd115909fa0bcbc76ca438 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 2 Nov 2014 15:06:12 +0400 Subject: [PATCH 26/53] add elixir mode --- demo/kitchen-sink/docs/elixir.ex | 1 + lib/ace/ext/modelist.js | 1 + lib/ace/mode/elixir.js | 58 ++++ lib/ace/mode/elixir_highlight_rules.js | 435 +++++++++++++++++++++++++ 4 files changed, 495 insertions(+) create mode 100644 demo/kitchen-sink/docs/elixir.ex create mode 100644 lib/ace/mode/elixir.js create mode 100644 lib/ace/mode/elixir_highlight_rules.js diff --git a/demo/kitchen-sink/docs/elixir.ex b/demo/kitchen-sink/docs/elixir.ex new file mode 100644 index 00000000..ec0cfb59 --- /dev/null +++ b/demo/kitchen-sink/docs/elixir.ex @@ -0,0 +1 @@ +TODO add a nice demo! \ No newline at end of file diff --git a/lib/ace/ext/modelist.js b/lib/ace/ext/modelist.js index 3f85c5b3..9e012f51 100644 --- a/lib/ace/ext/modelist.js +++ b/lib/ace/ext/modelist.js @@ -69,6 +69,7 @@ var supportedModes = { DummySyntax: ["dummy"], Eiffel: ["e"], EJS: ["ejs"], + Elixir: ["ex|exs"], Elm: ["elm"], Erlang: ["erl|hrl"], Forth: ["frt|fs|ldr"], diff --git a/lib/ace/mode/elixir.js b/lib/ace/mode/elixir.js new file mode 100644 index 00000000..c64f5cce --- /dev/null +++ b/lib/ace/mode/elixir.js @@ -0,0 +1,58 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2012, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +/* + THIS FILE WAS AUTOGENERATED BY mode.tmpl.js +*/ + +define(function(require, exports, module) { +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var ElixirHighlightRules = require("./elixir_highlight_rules").ElixirHighlightRules; +// TODO: pick appropriate fold mode +var FoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = ElixirHighlightRules; + this.foldingRules = new FoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + // this.lineCommentStart = ""@(?:module|type)?doc \"""; + // this.blockComment = {start: ""/*"", end: ""*/""}; + // Extra logic goes here. + this.$id = "ace/mode/elixir" +}).call(Mode.prototype); + +exports.Mode = Mode; +}); \ No newline at end of file diff --git a/lib/ace/mode/elixir_highlight_rules.js b/lib/ace/mode/elixir_highlight_rules.js new file mode 100644 index 00000000..a52bdf4f --- /dev/null +++ b/lib/ace/mode/elixir_highlight_rules.js @@ -0,0 +1,435 @@ +/* ***** 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.githubusercontent.com/elixir-lang/elixir-tmbundle/master/Syntaxes/Elixir.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 ElixirHighlightRules = function() { + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { start: + [ { token: + [ 'meta.module.elixir', + 'keyword.control.module.elixir', + 'meta.module.elixir', + 'entity.name.type.module.elixir' ], + regex: '^(\\s*)(defmodule)(\\s+)((?:[A-Z]\\w*\\s*\\.\\s*)*[A-Z]\\w*)' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc (?:~[a-z])?"""', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*"""', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc ~[A-Z]"""', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*"""', + next: 'pop' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc (?:~[a-z])?\'\'\'', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*\'\'\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.heredoc', + regex: '@(?:module|type)?doc ~[A-Z]\'\'\'', + push: + [ { token: 'comment.documentation.heredoc', + regex: '\\s*\'\'\'', + next: 'pop' }, + { defaultToken: 'comment.documentation.heredoc' } ], + comment: '@doc with heredocs is treated as documentation' }, + { token: 'comment.documentation.false', + regex: '@(?:module|type)?doc false', + comment: '@doc false is treated as documentation' }, + { token: 'comment.documentation.string', + regex: '@(?:module|type)?doc "', + push: + [ { token: 'comment.documentation.string', + regex: '"', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'comment.documentation.string' } ], + comment: '@doc with string is treated as documentation' }, + { token: 'keyword.control.elixir', + regex: '(?_?[\\da-fA-F])*|\\d(?>_?\\d)*(?:\\.(?![^[:space:][:digit:]])(?>_?\\d)*)?(?:[eE][-+]?\\d(?>_?\\d)*)?|0b[01]+|0o[0-7]+)\\b', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '\\b(0x\\h(?>_?\\h)*|\\d(?>_?\\d)*(\\.(?![^[:space:][:digit:]])(?>_?\\d)*)?([eE][-+]?\\d(?>_?\\d)*)?|0b[01]+|0o[0-7]+)\\b' }, + { token: 'punctuation.definition.constant.elixir', + regex: ':\'', + push: + [ { token: 'punctuation.definition.constant.elixir', + regex: '\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'constant.other.symbol.single-quoted.elixir' } ] }, + { token: 'punctuation.definition.constant.elixir', + regex: ':"', + push: + [ { token: 'punctuation.definition.constant.elixir', + regex: '"', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'constant.other.symbol.double-quoted.elixir' } ] }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '(?>\'\'\')', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?>\'\'\')', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*\'\'\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'support.function.variable.quoted.single.heredoc.elixir' } ], + comment: 'Single-quoted heredocs' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '\'', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\'', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'support.function.variable.quoted.single.elixir' } ], + comment: 'single quoted string (allows for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '(?>""")', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?>""")', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*"""', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.quoted.double.heredoc.elixir' } ], + comment: 'Double-quoted heredocs' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '"', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '"', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.quoted.double.elixir' } ], + comment: 'double quoted string (allows for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z](?>""")', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '~[a-z](?>""")', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*"""', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.quoted.double.heredoc.elixir' } ], + comment: 'Double-quoted heredocs sigils' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\{', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\}[a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\[', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\][a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\<', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\>[a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z]\\(', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\)[a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[a-z][^\\w]', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '[^\\w][a-z]*', + next: 'pop' }, + { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { include: '#escaped_char' }, + { defaultToken: 'string.interpolated.elixir' } ], + comment: 'sigil (allow for interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z](?>""")', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '~[A-Z](?>""")', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '^\\s*"""', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'Double-quoted heredocs sigils' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\{', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\}[a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\[', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\][a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\<', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\>[a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z]\\(', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '\\)[a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.string.begin.elixir', + regex: '~[A-Z][^\\w]', + push: + [ { token: 'punctuation.definition.string.end.elixir', + regex: '[^\\w][a-z]*', + next: 'pop' }, + { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], + comment: 'sigil (without interpolation)' }, + { token: 'punctuation.definition.constant.elixir', + regex: '(?[a-zA-Z_][\\w@]*(?>[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(?:\\^\\^)?)', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?[a-zA-Z_][\\w@]*(?>[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(\\^\\^)?)', + comment: 'symbols' }, + { token: 'punctuation.definition.constant.elixir', + regex: '(?>[a-zA-Z_][\\w@]*(?>[?!])?):(?!:)', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?>[a-zA-Z_][\\w@]*(?>[?!])?)(:)(?!:)', + comment: 'symbols' }, + { token: + [ 'punctuation.definition.comment.elixir', + 'comment.line.number-sign.elixir' ], + regex: '(?:^[ \\t]+)?(#)(.*$)' }, + { token: 'constant.numeric.elixir', + regex: '(?=?' }, + { token: 'keyword.operator.bitwise.elixir', + regex: '\\|\\|\\||&&&|^^^|<<<|>>>|~~~' }, + { token: 'keyword.operator.logical.elixir', + regex: '(?<=[ \\t])!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?<=[ \\t])!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b' }, + { token: 'keyword.operator.arithmetic.elixir', + regex: '\\*|\\+|\\-|/' }, + { token: 'keyword.operator.other.elixir', + regex: '\\||\\+\\+|\\-\\-|\\*\\*|\\\\\\\\|\\<\\-|\\<\\>|\\<\\<|\\>\\>|\\:\\:|\\.\\.|\\|>|~|=>' }, + { token: 'keyword.operator.assignment.elixir', regex: '=' }, + { token: 'punctuation.separator.other.elixir', regex: ':' }, + { token: 'punctuation.separator.statement.elixir', + regex: '\\;' }, + { token: 'punctuation.separator.object.elixir', regex: ',' }, + { token: 'punctuation.separator.method.elixir', regex: '\\.' }, + { token: 'punctuation.section.scope.elixir', regex: '\\{|\\}' }, + { token: 'punctuation.section.array.elixir', regex: '\\[|\\]' }, + { token: 'punctuation.section.function.elixir', + regex: '\\(|\\)' } ], + '#escaped_char': + [ { token: 'constant.character.escape.elixir', + regex: '\\\\(?:x[\\da-fA-F]{1,2}|.)' } ], + '#interpolated_elixir': + [ { token: + [ 'source.elixir.embedded.source', + 'source.elixir.embedded.source.empty' ], + regex: '(#\\{)(\\})' }, + { todo: + { token: 'punctuation.section.embedded.elixir', + regex: '#\\{', + push: + [ { token: 'punctuation.section.embedded.elixir', + regex: '\\}', + next: 'pop' }, + { include: '#nest_curly_and_self' }, + { include: '$self' }, + { defaultToken: 'source.elixir.embedded.source' } ] } } ], + '#nest_curly_and_self': + [ { token: 'punctuation.section.scope.elixir', + regex: '\\{', + push: + [ { token: 'punctuation.section.scope.elixir', + regex: '\\}', + next: 'pop' }, + { include: '#nest_curly_and_self' } ] }, + { include: '$self' } ], + '#regex_sub': + [ { include: '#interpolated_elixir' }, + { include: '#escaped_char' }, + { token: + [ 'punctuation.definition.arbitrary-repitition.elixir', + 'string.regexp.arbitrary-repitition.elixir', + 'string.regexp.arbitrary-repitition.elixir', + 'punctuation.definition.arbitrary-repitition.elixir' ], + regex: '(\\{)(\\d+)((?:,\\d+)?)(\\})' }, + { token: 'punctuation.definition.character-class.elixir', + regex: '\\[(?:\\^?\\])?', + push: + [ { token: 'punctuation.definition.character-class.elixir', + regex: '\\]', + next: 'pop' }, + { include: '#escaped_char' }, + { defaultToken: 'string.regexp.character-class.elixir' } ] }, + { token: 'punctuation.definition.group.elixir', + regex: '\\(', + push: + [ { token: 'punctuation.definition.group.elixir', + regex: '\\)', + next: 'pop' }, + { include: '#regex_sub' }, + { defaultToken: 'string.regexp.group.elixir' } ] }, + { token: + [ 'punctuation.definition.comment.elixir', + 'comment.line.number-sign.elixir' ], + regex: '(?<=^|\\s)(#)(\\s[[a-zA-Z0-9,. \\t?!-][^\\x00-\\x7F]]*$)', + TODO: 'FIXME: regexp doesn\'t have js equivalent', + originalRegex: '(?<=^|\\s)(#)\\s[[a-zA-Z0-9,. \\t?!-][^\\x{00}-\\x{7F}]]*$', + comment: 'We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.' } ] } + + this.normalizeRules(); +}; + +ElixirHighlightRules.metaData = { comment: 'Textmate bundle for Elixir Programming Language.', + fileTypes: [ 'ex', 'exs' ], + firstLineMatch: '^#!/.*\\belixir', + foldingStartMarker: '(after|else|catch|rescue|\\-\\>|\\{|\\[|do)\\s*$', + foldingStopMarker: '^\\s*((\\}|\\]|after|else|catch|rescue)\\s*$|end\\b)', + keyEquivalent: '^~E', + name: 'Elixir', + scopeName: 'source.elixir' } + + +oop.inherits(ElixirHighlightRules, TextHighlightRules); + +exports.ElixirHighlightRules = ElixirHighlightRules; +}); \ No newline at end of file From 399e25ceaf58c7c3d1505715f41535ef0406947a Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 2 Nov 2014 15:04:55 +0400 Subject: [PATCH 27/53] fix errors in imported elixir mode --- demo/kitchen-sink/docs/elixir.ex | 25 +++++++++++++++++- lib/ace/mode/elixir.js | 4 +-- lib/ace/mode/elixir_highlight_rules.js | 36 ++++++++++++-------------- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/demo/kitchen-sink/docs/elixir.ex b/demo/kitchen-sink/docs/elixir.ex index ec0cfb59..693a4bb1 100644 --- a/demo/kitchen-sink/docs/elixir.ex +++ b/demo/kitchen-sink/docs/elixir.ex @@ -1 +1,24 @@ -TODO add a nice demo! \ No newline at end of file +defmodule HelloModule do + # A "Hello world" function + def some_fun do + IO.puts "Juhu Kinners!" + end + # A private function + defp priv do + is_regex ~r""" + This is a regex + spanning several + lines. + """ + x = elem({ :a, :b, :c }, 0) #=> :a + end +end + +test_fun = fn(x) -> + cond do + x > 10 -> + :greater_than_ten + true -> + :maybe_ten + end +end \ No newline at end of file diff --git a/lib/ace/mode/elixir.js b/lib/ace/mode/elixir.js index c64f5cce..c55ea366 100644 --- a/lib/ace/mode/elixir.js +++ b/lib/ace/mode/elixir.js @@ -39,7 +39,7 @@ var oop = require("../lib/oop"); var TextMode = require("./text").Mode; var ElixirHighlightRules = require("./elixir_highlight_rules").ElixirHighlightRules; // TODO: pick appropriate fold mode -var FoldMode = require("./folding/cstyle").FoldMode; +var FoldMode = require("./folding/coffee").FoldMode; var Mode = function() { this.HighlightRules = ElixirHighlightRules; @@ -48,7 +48,7 @@ var Mode = function() { oop.inherits(Mode, TextMode); (function() { - // this.lineCommentStart = ""@(?:module|type)?doc \"""; + this.lineCommentStart = "#"; // this.blockComment = {start: ""/*"", end: ""*/""}; // Extra logic goes here. this.$id = "ace/mode/elixir" diff --git a/lib/ace/mode/elixir_highlight_rules.js b/lib/ace/mode/elixir_highlight_rules.js index a52bdf4f..a13492be 100644 --- a/lib/ace/mode/elixir_highlight_rules.js +++ b/lib/ace/mode/elixir_highlight_rules.js @@ -101,11 +101,11 @@ var ElixirHighlightRules = function() { { defaultToken: 'comment.documentation.string' } ], comment: '@doc with string is treated as documentation' }, { token: 'keyword.control.elixir', - regex: '(?_?[\\da-fA-F])*|\\d(?>_?\\d)*(?:\\.(?![^[:space:][:digit:]])(?>_?\\d)*)?(?:[eE][-+]?\\d(?>_?\\d)*)?|0b[01]+|0o[0-7]+)\\b', + regex: '\\b(?:0x[\\da-fA-F](?:_?[\\da-fA-F])*|\\d(?:_?\\d)*(?:\\.(?![^[:space:][:digit:]])(?:_?\\d)*)?(?:[eE][-+]?\\d(?:_?\\d)*)?|0b[01]+|0o[0-7]+)\\b', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '\\b(0x\\h(?>_?\\h)*|\\d(?>_?\\d)*(\\.(?![^[:space:][:digit:]])(?>_?\\d)*)?([eE][-+]?\\d(?>_?\\d)*)?|0b[01]+|0o[0-7]+)\\b' }, { token: 'punctuation.definition.constant.elixir', @@ -146,7 +146,7 @@ var ElixirHighlightRules = function() { { include: '#escaped_char' }, { defaultToken: 'constant.other.symbol.double-quoted.elixir' } ] }, { token: 'punctuation.definition.string.begin.elixir', - regex: '(?>\'\'\')', + regex: '(?:\'\'\')', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '(?>\'\'\')', push: @@ -168,7 +168,7 @@ var ElixirHighlightRules = function() { { defaultToken: 'support.function.variable.quoted.single.elixir' } ], comment: 'single quoted string (allows for interpolation)' }, { token: 'punctuation.definition.string.begin.elixir', - regex: '(?>""")', + regex: '(?:""")', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '(?>""")', push: @@ -190,7 +190,7 @@ var ElixirHighlightRules = function() { { defaultToken: 'string.quoted.double.elixir' } ], comment: 'double quoted string (allows for interpolation)' }, { token: 'punctuation.definition.string.begin.elixir', - regex: '~[a-z](?>""")', + regex: '~[a-z](?:""")', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '~[a-z](?>""")', push: @@ -253,7 +253,7 @@ var ElixirHighlightRules = function() { { defaultToken: 'string.interpolated.elixir' } ], comment: 'sigil (allow for interpolation)' }, { token: 'punctuation.definition.string.begin.elixir', - regex: '~[A-Z](?>""")', + regex: '~[A-Z](?:""")', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '~[A-Z](?>""")', push: @@ -302,26 +302,26 @@ var ElixirHighlightRules = function() { next: 'pop' }, { defaultToken: 'string.quoted.other.literal.upper.elixir' } ], comment: 'sigil (without interpolation)' }, - { token: 'punctuation.definition.constant.elixir', - regex: '(?[a-zA-Z_][\\w@]*(?>[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(?:\\^\\^)?)', + { token: ['punctuation.definition.constant.elixir', 'constant.other.symbol.elixir'], + regex: '(:)([a-zA-Z_][\\w@]*(?:[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(?:\\^\\^)?)', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '(?[a-zA-Z_][\\w@]*(?>[?!]|=(?![>=]))?|\\<\\>|===?|!==?|<<>>|<<<|>>>|~~~|::|<\\-|\\|>|=>|~|~=|=|/|\\\\\\\\|\\*\\*?|\\.\\.?\\.?|>=?|<=?|&&?&?|\\+\\+?|\\-\\-?|\\|\\|?\\|?|\\!|@|\\%?\\{\\}|%|\\[\\]|\\^(\\^\\^)?)', comment: 'symbols' }, { token: 'punctuation.definition.constant.elixir', - regex: '(?>[a-zA-Z_][\\w@]*(?>[?!])?):(?!:)', + regex: '(?:[a-zA-Z_][\\w@]*(?:[?!])?):(?!:)', TODO: 'FIXME: regexp doesn\'t have js equivalent', originalRegex: '(?>[a-zA-Z_][\\w@]*(?>[?!])?)(:)(?!:)', comment: 'symbols' }, { token: [ 'punctuation.definition.comment.elixir', 'comment.line.number-sign.elixir' ], - regex: '(?:^[ \\t]+)?(#)(.*$)' }, + regex: '(#)(.*)' }, { token: 'constant.numeric.elixir', - regex: '(?=?' }, { token: 'keyword.operator.bitwise.elixir', - regex: '\\|\\|\\||&&&|^^^|<<<|>>>|~~~' }, + regex: '\\|{3}|&{3}|\\^{3}|<{3}|>{3}|~{3}' }, { token: 'keyword.operator.logical.elixir', - regex: '(?<=[ \\t])!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b', - TODO: 'FIXME: regexp doesn\'t have js equivalent', + regex: '!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b', originalRegex: '(?<=[ \\t])!+|\\bnot\\b|&&|\\band\\b|\\|\\||\\bor\\b|\\bxor\\b' }, { token: 'keyword.operator.arithmetic.elixir', regex: '\\*|\\+|\\-|/' }, @@ -411,8 +410,7 @@ var ElixirHighlightRules = function() { { token: [ 'punctuation.definition.comment.elixir', 'comment.line.number-sign.elixir' ], - regex: '(?<=^|\\s)(#)(\\s[[a-zA-Z0-9,. \\t?!-][^\\x00-\\x7F]]*$)', - TODO: 'FIXME: regexp doesn\'t have js equivalent', + regex: '(?:^|\\s)(#)(\\s[[a-zA-Z0-9,. \\t?!-][^\\x00-\\x7F]]*$)', originalRegex: '(?<=^|\\s)(#)\\s[[a-zA-Z0-9,. \\t?!-][^\\x{00}-\\x{7F}]]*$', comment: 'We are restrictive in what we allow to go after the comment character to avoid false positives, since the availability of comments depend on regexp flags.' } ] } From c83f39e4a9f9f7529cb064f2252c3dbb6a1f2752 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 2 Nov 2014 15:33:10 +0400 Subject: [PATCH 28/53] update tests for ruby mode --- lib/ace/mode/_test/tokens_html_ruby.json | 20 +++++++++++++++----- lib/ace/mode/_test/tokens_ruby.json | 4 +++- lib/ace/mode/_test/tokens_sh.json | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/ace/mode/_test/tokens_html_ruby.json b/lib/ace/mode/_test/tokens_html_ruby.json index 2c74ba56..8ff5f6ea 100644 --- a/lib/ace/mode/_test/tokens_html_ruby.json +++ b/lib/ace/mode/_test/tokens_html_ruby.json @@ -144,7 +144,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'Show'"], + ["string.start","'"], + ["string","Show"], + ["string.end","'"], ["text",", "], ["identifier","book"], ["text"," "], @@ -162,7 +164,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'Edit'"], + ["string.start","'"], + ["string","Edit"], + ["string.end","'"], ["text",", "], ["identifier","edit_book_path"], ["paren.lparen","("], @@ -183,7 +187,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'Remove'"], + ["string.start","'"], + ["string","Remove"], + ["string.end","'"], ["text",", "], ["identifier","book"], ["text",", "], @@ -191,7 +197,9 @@ ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string","'Are you sure?'"], + ["string.start","'"], + ["string","Are you sure?"], + ["string.end","'"], ["text",", "], ["constant.other.symbol.ruby",":method"], ["text"," "], @@ -239,7 +247,9 @@ ["text"," "], ["support.function","link_to"], ["text"," "], - ["string","'New book'"], + ["string.start","'"], + ["string","New book"], + ["string.end","'"], ["text",", "], ["identifier","new_book_path"], ["text"," "], diff --git a/lib/ace/mode/_test/tokens_ruby.json b/lib/ace/mode/_test/tokens_ruby.json index 19b98b70..1809f5ee 100644 --- a/lib/ace/mode/_test/tokens_ruby.json +++ b/lib/ace/mode/_test/tokens_ruby.json @@ -145,7 +145,9 @@ ["text"," "], ["punctuation.separator.key-value","=>"], ["text"," "], - ["string","\"value\""], + ["string.start","\""], + ["string","value"], + ["string.end","\""], ["paren.rparen","}"] ],[ "start" diff --git a/lib/ace/mode/_test/tokens_sh.json b/lib/ace/mode/_test/tokens_sh.json index 53411906..f2c6b276 100644 --- a/lib/ace/mode/_test/tokens_sh.json +++ b/lib/ace/mode/_test/tokens_sh.json @@ -331,4 +331,4 @@ ["keyword","fi"] ],[ "start" -]] +]] \ No newline at end of file From 78cda6bc3a55a4973018ec242fe7acee6027825c Mon Sep 17 00:00:00 2001 From: nightwing Date: Sun, 2 Nov 2014 15:33:23 +0400 Subject: [PATCH 29/53] update architect-build --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9734fc52..e7a166dc 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "jsdom": "0.2.x", "amd-loader": "~0.0.4", "dryice": "0.4.11", - "architect-build": "https://github.com/c9/architect-build/tarball/42723e152bb" + "architect-build": "https://github.com/c9/architect-build/tarball/a3bad51808" }, "mappings": { "ace": "." From 70337ea5bae6f1a5eb07a81beea8020d7f969b95 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 16:42:39 +0400 Subject: [PATCH 30/53] fix infinite loop in soy mode and make tokenizer more robust --- lib/ace/mode/soy_template_highlight_rules.js | 2 +- lib/ace/tokenizer.js | 32 +++++++++++++++----- lib/ace/tokenizer_test.js | 32 ++++++++++++++++++-- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/lib/ace/mode/soy_template_highlight_rules.js b/lib/ace/mode/soy_template_highlight_rules.js index 50e3ae48..aa913fac 100644 --- a/lib/ace/mode/soy_template_highlight_rules.js +++ b/lib/ace/mode/soy_template_highlight_rules.js @@ -188,7 +188,7 @@ var SoyTemplateHighlightRules = function() { [ 'entity.other.attribute-name.soy', 'text', 'keyword.operator.soy' ], - regex: '\\b([\\w]*)(\\s*)((?::)?)' }, + regex: '\\b([\\w]+)(\\s*)((?::)?)' }, { defaultToken: 'meta.tag.param.soy' } ] } ], '#primitive': [ { token: 'constant.language.soy', diff --git a/lib/ace/tokenizer.js b/lib/ace/tokenizer.js index e947a130..a0756157 100644 --- a/lib/ace/tokenizer.js +++ b/lib/ace/tokenizer.js @@ -32,7 +32,7 @@ define(function(require, exports, module) { "use strict"; // tokenizing lines longer than this makes editor very slow -var MAX_TOKEN_COUNT = 1000; +var MAX_TOKEN_COUNT = 2000; /** * This class takes a set of highlighting rules, and creates a tokenizer out of them. For more information, see [the wiki on extending highlighters](https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode#wiki-extendingTheHighlighter). * @class Tokenizer @@ -77,9 +77,11 @@ var Tokenizer = function(rules) { if (rule.token.length == 1 || matchcount == 1) { rule.token = rule.token[0]; } else if (matchcount - 1 != rule.token.length) { - throw new Error("number of classes and regexp groups in '" + - rule.token + "'\n'" + rule.regex + "' doesn't match\n" - + (matchcount - 1) + "!=" + rule.token.length); + this.reportError("number of classes and regexp groups doesn't match", { + rule: rule, + groupCount: matchcount - 1 + }); + rule.token = rule.token[0]; } else { rule.tokenArray = rule.token; rule.token = null; @@ -240,6 +242,7 @@ var Tokenizer = function(rules) { var match, tokens = []; var lastIndex = 0; + var matchAttempts = 0; var token = {type: null, value: ""}; @@ -280,7 +283,7 @@ var Tokenizer = function(rules) { state = this.states[currentState]; if (!state) { - window.console && console.error && console.error(currentState, "doesn't exist"); + this.reportError("state doesn't exist", currentState); currentState = "start"; state = this.states[currentState]; } @@ -293,7 +296,7 @@ var Tokenizer = function(rules) { } if (value) { - if (typeof type == "string") { + if (typeof type === "string") { if ((!rule || rule.merge !== false) && token.type === type) { token.value += value; } else { @@ -315,7 +318,13 @@ var Tokenizer = function(rules) { lastIndex = index; - if (tokens.length > MAX_TOKEN_COUNT) { + if (matchAttempts++ > MAX_TOKEN_COUNT) { + if (matchAttempts > 2 * line.length) { + this.reportError("infinite loop with in ace tokenizer", { + startState: startState, + line: line + }); + } // chrome doens't show contents of text nodes with very long text while (lastIndex < line.length) { if (token.type) @@ -343,7 +352,14 @@ var Tokenizer = function(rules) { state : stack.length ? stack : currentState }; }; - + + this.reportError = function(msg, data) { + var e = new Error(msg); + e.data = data; + if (typeof console == "object" && console.error) + console.error(e); + setTimeout(function() { throw e; }); + }; }).call(Tokenizer.prototype); exports.Tokenizer = Tokenizer; diff --git a/lib/ace/tokenizer_test.js b/lib/ace/tokenizer_test.js index 281f58b3..41bf01c8 100644 --- a/lib/ace/tokenizer_test.js +++ b/lib/ace/tokenizer_test.js @@ -29,7 +29,7 @@ * ***** END LICENSE BLOCK ***** */ if (typeof process !== "undefined") { - require("amd-loader"); + require("amd-loader"); } define(function(require, exports, module) { @@ -59,7 +59,35 @@ module.exports = { var t = new Tokenizer({}); var re = t.removeCapturingGroups("(ax(by))[()]"); assert.equal(re, "(?:ax(?:by))[()]"); - } + }, + + "test: broken highlight rules": function() { + var t = new Tokenizer({ + start: [{ + token: 's', + regex: '&&&|^^^' + }, { + defaultToken: "def" + }], + state1: [{ + token: 'x', + regex: /\b([\w]*)(\s*)((?::)?)/ + }] + }); + var errorReports = 0; + t.reportError = function() { errorReports++; }; + var tokens = t.getLineTokens("x|", "start"); + assert.deepEqual(tokens, { + tokens: [{value: 'x|', type: 'overflow'}], + state: 'start' + }); + var tokens = t.getLineTokens("x|", "state1"); + assert.deepEqual(tokens, { + tokens: [{value: 'x', type: 'x'}, {value: '|', type: 'overflow'}], + state: 'start' + }); + assert.equal(errorReports, 2); + }, }; }); From 96061f72aef6f63843642b84b11518ddb3768870 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 16:51:34 +0400 Subject: [PATCH 31/53] update ChangeLog --- ChangeLog.txt | 11 +++++++++-- tool/tmlanguage.js | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index 7c3db96d..86399b5e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,8 +1,15 @@ - + + * 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 diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index d3e42141..9261a2f1 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -107,7 +107,7 @@ function convertToNonCapturingGroups(str) { function simplifyNonCapturingGroups(str) { var tokens = tokenize(str); - var t = tokens[0]; + var t = tokens[0] || {}; if (t.type == "group.start" && t.value == "(?:" && t.end == last(tokens)) { t.value = t.end.value = ""; From f362d2e84abbfd76ccf189bb0cf8ac21976f84f7 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 16:56:51 +0400 Subject: [PATCH 32/53] add markdown comment to elixir demo --- demo/kitchen-sink/docs/elixir.ex | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/demo/kitchen-sink/docs/elixir.ex b/demo/kitchen-sink/docs/elixir.ex index 693a4bb1..bb6a45f1 100644 --- a/demo/kitchen-sink/docs/elixir.ex +++ b/demo/kitchen-sink/docs/elixir.ex @@ -1,4 +1,22 @@ defmodule HelloModule do + @moduledoc """ + This is supposed to be `markdown`. + __Yes__ this is [mark](http://down.format) + + # Truly + + ## marked + + * with lists + * more + * and more + + Even.with(code) + blocks |> with |> samples + + _Docs are first class citizens in Elixir_ (Jose Valim) + """ + # A "Hello world" function def some_fun do IO.puts "Juhu Kinners!" From e26c70ad53a375a99b6844df1833f764023bf0b8 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 17:36:14 +0400 Subject: [PATCH 33/53] update soy_template test --- lib/ace/mode/_test/highlight_rules_test.js | 5 +++-- lib/ace/mode/_test/tokens_soy_template.json | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/ace/mode/_test/highlight_rules_test.js b/lib/ace/mode/_test/highlight_rules_test.js index e0244abc..c3b877ec 100644 --- a/lib/ace/mode/_test/highlight_rules_test.js +++ b/lib/ace/mode/_test/highlight_rules_test.js @@ -63,8 +63,8 @@ function generateTestData() { var specialDocs = fs.readdirSync(cwd); var modes = modeList(); - 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("."); @@ -92,6 +92,7 @@ function generateTestData() { console.warn("Can't load mode :" + modeName, p, e); return; } + console.log(modeName); var tokenizer = new Mode().getTokenizer(); var state = "start"; diff --git a/lib/ace/mode/_test/tokens_soy_template.json b/lib/ace/mode/_test/tokens_soy_template.json index 46ea77fa..9ae7c4ed 100644 --- a/lib/ace/mode/_test/tokens_soy_template.json +++ b/lib/ace/mode/_test/tokens_soy_template.json @@ -157,13 +157,12 @@ ["text.xml"," "], ["punctuation.definition.tag.begin.soy","{"], ["entity.name.tag.soy","param"], - ["text"," "], + ["meta.tag.param.soy"," "], ["entity.other.attribute-name.soy","name"], ["keyword.operator.soy",":"], ["meta.tag.param.soy"," "], ["variable.other.soy","$additionalName"], - ["text"," "], - ["meta.tag.param.soy","/"], + ["meta.tag.param.soy"," /"], ["punctuation.definition.tag.end.soy","}"] ],[ "start", From 22de93672735cb6ad39cd131727cb49ca13f2c24 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 23:15:45 +0400 Subject: [PATCH 34/53] fix bracket pairing for multiple selections --- lib/ace/mode/behaviour/behaviour_test.js | 133 +++++++++++++++++++++++ lib/ace/mode/behaviour/cstyle.js | 4 +- lib/ace/multi_select_test.js | 28 ++--- lib/ace/test/all_browser.js | 1 + 4 files changed, 147 insertions(+), 19 deletions(-) create mode 100644 lib/ace/mode/behaviour/behaviour_test.js diff --git a/lib/ace/mode/behaviour/behaviour_test.js b/lib/ace/mode/behaviour/behaviour_test.js new file mode 100644 index 00000000..33a09c83 --- /dev/null +++ b/lib/ace/mode/behaviour/behaviour_test.js @@ -0,0 +1,133 @@ +/* ***** 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"); +} + +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 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 = { + + name: "ACE multi_select.js", + + "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}") + } +}; + +}); + +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 2709168e..a8a18e72 100644 --- a/lib/ace/mode/behaviour/cstyle.js +++ b/lib/ace/mode/behaviour/cstyle.js @@ -42,11 +42,11 @@ var SAFE_INSERT_BEFORE_TOKENS = ["text", "paren.rparen", "punctuation.operator", "comment"]; var context; -var contextCache = {} +var contextCache = {}; var initContext = function(editor) { var id = -1; if (editor.multiSelect) { - id = editor.selection.id; + id = editor.selection.index; if (contextCache.rangeCount != editor.multiSelect.rangeCount) contextCache = {rangeCount: editor.multiSelect.rangeCount}; } diff --git a/lib/ace/multi_select_test.js b/lib/ace/multi_select_test.js index 45ab4965..2e71aefa 100644 --- a/lib/ace/multi_select_test.js +++ b/lib/ace/multi_select_test.js @@ -35,22 +35,22 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -var EditSession = require("./edit_session").EditSession; -var Editor = require("./editor").Editor; -var MockRenderer = require("./test/mockrenderer").MockRenderer; -var Range = require("./range").Range; +require("./multi_select"); var assert = require("./test/assertions"); -var MultiSelect = require("./multi_select").MultiSelect; +var Range = require("./range").Range; +var Editor = require("./editor").Editor; +var EditSession = require("./edit_session").EditSession; +var MockRenderer = require("./test/mockrenderer").MockRenderer; var editor; var exec = function(name, times, args) { do { editor.commands.exec(name, editor, args); - } while(times --> 1) + } while(times --> 1); }; var testRanges = function(str) { assert.equal(editor.selection.getAllRanges() + "", str + ""); -} +}; module.exports = { @@ -63,7 +63,6 @@ module.exports = { " wtt.w" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); editor.navigateFileEnd(); exec("selectMoreBefore", 3); @@ -90,7 +89,6 @@ module.exports = { " wtt.we" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); editor.selectMoreLines(1); testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]"); @@ -113,9 +111,8 @@ module.exports = { " wtt.w" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); - editor.selectMoreLines(1) + editor.selectMoreLines(1); testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]"); assert.ok(editor.inMultiSelectMode); @@ -134,7 +131,6 @@ module.exports = { " wtt.w" ]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); var selection = editor.selection; var range1 = new Range(0, 2, 0, 4); @@ -158,7 +154,6 @@ module.exports = { "test: onPaste in command with multiselect": function() { var doc = new EditSession(["l1", "l2"]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); editor.commands.addCommand({ name: 'insertfoo', exec: function(ed) { ed.onPaste('foo'); }, @@ -167,7 +162,7 @@ module.exports = { var selection = editor.selection; var range1 = new Range(0,2,0,2); var range2 = new Range(1,2,1,2); - selection.fromOrientedRange(range1) + selection.fromOrientedRange(range1); selection.addRange(range2); editor.execCommand('insertfoo'); assert.equal('l1foo\nl2foo', editor.getValue()); @@ -176,14 +171,13 @@ module.exports = { "test multiselect fromJSON/toJSON": function() { var doc = new EditSession(["l1", "l2"]); editor = new Editor(new MockRenderer(), doc); - MultiSelect(editor); var selection = editor.selection; var before = selection.toJSON(); var range1 = new Range(0,2,0,2); var range2 = new Range(1,2,1,2); - selection.fromOrientedRange(range1) + selection.fromOrientedRange(range1); selection.addRange(range2); var after = selection.toJSON(); @@ -201,5 +195,5 @@ module.exports = { }); if (typeof module !== "undefined" && module === require.main) { - require("asyncjs").test.testcase(module.exports).exec() + require("asyncjs").test.testcase(module.exports).exec(); } diff --git a/lib/ace/test/all_browser.js b/lib/ace/test/all_browser.js index 3b7bf5d9..9b5742dd 100644 --- a/lib/ace/test/all_browser.js +++ b/lib/ace/test/all_browser.js @@ -43,6 +43,7 @@ var testNames = [ "ace/mode/folding/pythonic_test", "ace/mode/folding/xml_test", "ace/mode/folding/coffee_test", + "ace/mode/behaviour/behaviour_test", "ace/multi_select_test", "ace/mouse/mouse_handler_test", "ace/occur_test", From 9ccf68dbb297429d5c28ee19483b879effbc08d2 Mon Sep 17 00:00:00 2001 From: nightwing Date: Wed, 5 Nov 2014 23:17:59 +0400 Subject: [PATCH 35/53] make sure missing emmet can't break tab key --- lib/ace/ext/emmet.js | 49 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/lib/ace/ext/emmet.js b/lib/ace/ext/emmet.js index 75eefa3f..ceb155ef 100644 --- a/lib/ace/ext/emmet.js +++ b/lib/ace/ext/emmet.js @@ -342,29 +342,29 @@ var keymap = { var editorProxy = new AceEmmetEditor(); exports.commands = new HashHandler(); exports.runEmmetCommand = function(editor) { - 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; - } - - 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; - try { + 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; + } + + 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; + var result = actions.run(this.action, editorProxy); } catch(e) { editor._signal("changeStatus", typeof e == "string" ? e : e.message); @@ -393,7 +393,7 @@ exports.updateCommands = function(editor, enabled) { }; exports.isSupportedMode = function(modeId) { - return modeId && /css|less|scss|sass|stylus|html|php|twig/.test(modeId); + return modeId && /css|less|scss|sass|stylus|html|php|twig|ejs/.test(modeId); }; var onChangeMode = function(e, target) { @@ -406,9 +406,8 @@ var onChangeMode = function(e, target) { if (enabled) { if (typeof emmetPath == "string") { require("ace/config").loadModule(emmetPath, function() { - + emmetPath = null; }); - emmetPath = null; } } exports.updateCommands(editor, enabled); From 90034c3a44d6da0d56feb918b6b148f04ea7af60 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Fri, 21 Mar 2014 22:41:46 -0700 Subject: [PATCH 36/53] fixing multi selection handling for various emacs commands Conflicts: lib/ace/keyboard/emacs.js --- lib/ace/keyboard/emacs.js | 65 ++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index ab4471b2..fd533f1d 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -318,7 +318,8 @@ 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 { @@ -439,37 +440,39 @@ 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 + // setMark twice in a row at the same place resets markmode. + // in multi select mode, ea selection is handled individually + if (args && args.count) { - var mark = editor.popEmacsMark(); - mark && editor.selection.moveCursorToPosition(mark); + function moveToMark() { + var mark = editor.popEmacsMark(); + mark && editor.moveCursorToPosition(mark); + } + if (editor.inMultiSelectMode) editor.forEachSelection({exec: moveToMark}); + else moveToMark(); return; } var mark = editor.emacsMark(), - transientMarkModeActive = true; - + 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(); }); // if transientMarkModeActive then mark behavior is a little // different. Deactivate the mark when setMark is run with active // mark - if (transientMarkModeActive && (mark || !editor.selection.isEmpty())) { - editor.pushEmacsMark(); - editor.clearSelection(); + if (transientMarkModeActive && (mark || !hasNoSelection)) { + if (editor.inMultiSelectMode) editor.forEachSelection({exec: editor.clearSelection.bind(editor)}) + else editor.clearSelection(); + if (mark) editor.pushEmacsMark(null); return; } - if (mark) { - var cp = editor.getCursorPosition(); - if (editor.selection.isEmpty() && - mark.row == cp.row && mark.column == cp.column) { - editor.pushEmacsMark(); - return; - } + if (!mark) { + rangePositions.slice(0,-1).forEach(function(pos) { editor.pushEmacsMark(pos); }); + editor.setEmacsMark(rangePositions[rangePositions.length-1]); + return; } - // turn on mark mode - mark = editor.getCursorPosition(); - editor.setEmacsMark(mark); - editor.selection.setSelectionAnchor(mark.row, mark.column); }, readOnly: true, handlesCount: true, @@ -544,6 +547,7 @@ 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"; }, @@ -557,12 +561,25 @@ exports.handler.addCommands({ }, 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() { - var sel = editor.selection, - range = sel.getRange(); - editor.pushEmacsMark(sel.isBackwards() ? range.end : range.start); - sel.clearSelection(); + 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()); }, 0); }, readOnly: true From 24f3bab19d570bf74919e6801ad0afe296f5d92b Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sat, 22 Mar 2014 01:11:23 -0700 Subject: [PATCH 37/53] emacs: fix multi select exchangePointAndMark Conflicts: lib/ace/keyboard/emacs.js --- lib/ace/keyboard/emacs.js | 42 +++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index fd533f1d..38e29f96 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -442,7 +442,7 @@ exports.handler.addCommands({ // 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 - + if (args && args.count) { function moveToMark() { var mark = editor.popEmacsMark(); @@ -452,7 +452,7 @@ exports.handler.addCommands({ else moveToMark(); return; } - + var mark = editor.emacsMark(), ranges = editor.selection.getAllRanges(), rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }), @@ -467,7 +467,7 @@ exports.handler.addCommands({ if (mark) editor.pushEmacsMark(null); return; } - + if (!mark) { rangePositions.slice(0,-1).forEach(function(pos) { editor.pushEmacsMark(pos); }); editor.setEmacsMark(rangePositions[rangePositions.length-1]); @@ -479,22 +479,26 @@ exports.handler.addCommands({ multiSelectAction: "forEach" }, exchangePointAndMark: { - exec: function(editor, args) { - var sel = editor.selection; - if (args.count) { - var pos = editor.getCursorPosition(); - sel.clearSelection(); - sel.moveCursorToPosition(editor.popEmacsMark()); - editor.pushEmacsMark(pos); - return; - } - var lastMark = editor.getLastEmacsMark(); - var range = sel.getRange(); - if (range.isEmpty()) { - sel.selectToPosition(lastMark); - return; - } - sel.setSelectionRange(range, !sel.isBackwards()); + exec: function (editor, args) { + var restoreMarks = []; + editor.forEachSelection({ + exec: function() { + var sel = editor.selection; + if (args.count) { // replace mark and point + var pos = {row: sel.lead.row, column: sel.lead.column}; + restoreMarks.push(pos); + sel.clearSelection(); + sel.moveCursorToPosition(editor.popEmacsMark()); + } else if (sel.isEmpty()) { // move to mark, forget point + var lastMark = editor.popEmacsMark(); + restoreMarks.push(lastMark); + sel.selectToPosition(lastMark); + } else { // just invert selection + sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); + } + } + }); + restoreMarks.reverse().forEach(function(p) { editor.pushEmacsMark(p); }); }, readOnly: true, handlesCount: true, From b966cfd7da9ea0a00f9a9a64038be46e6dc22f3c Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Sat, 22 Mar 2014 01:11:23 -0700 Subject: [PATCH 38/53] emacs: cleanup --- lib/ace/keyboard/emacs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 38e29f96..7c88af38 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -442,7 +442,7 @@ exports.handler.addCommands({ // 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 - + if (args && args.count) { function moveToMark() { var mark = editor.popEmacsMark(); @@ -452,7 +452,7 @@ exports.handler.addCommands({ else moveToMark(); return; } - + var mark = editor.emacsMark(), ranges = editor.selection.getAllRanges(), rangePositions = ranges.map(function(r) { return {row: r.start.row, column: r.start.column}; }), @@ -467,7 +467,7 @@ exports.handler.addCommands({ if (mark) editor.pushEmacsMark(null); return; } - + if (!mark) { rangePositions.slice(0,-1).forEach(function(pos) { editor.pushEmacsMark(pos); }); editor.setEmacsMark(rangePositions[rangePositions.length-1]); From 78b2147c3c9cf5744863ea6db9273d6be05834a3 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Mon, 24 Mar 2014 16:15:59 -0700 Subject: [PATCH 39/53] emacs/isearch: select when moving cursor via isearch and emacs mark is set --- lib/ace/incremental_search.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ace/incremental_search.js b/lib/ace/incremental_search.js index 88615006..ee74f60d 100644 --- a/lib/ace/incremental_search.js +++ b/lib/ace/incremental_search.js @@ -140,10 +140,11 @@ oop.inherits(IncrementalSearch, Search); // try to find the next occurence and enable highlighting marker options.start = this.$currentPos; var session = this.$editor.session, - found = this.find(session); + found = this.find(session), + shouldSelect = !!this.$editor.emacsMark(); if (found) { if (options.backwards) found = Range.fromPoints(found.end, found.start); - this.$editor.moveCursorToPosition(found.end); + this.$editor.selection.setRange(Range.fromPoints(shouldSelect ? this.$startPos : found.end, found.end)); if (moveToNext) this.$currentPos = found.end; // highlight after cursor move, so selection works properly this.highlight(options.re) From ea67201540eedf6dd2347e9fa9c1d0fd6d738789 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Mon, 24 Mar 2014 16:16:54 -0700 Subject: [PATCH 40/53] emacs: fix exchangePointAndMark in normal select mode --- lib/ace/keyboard/emacs.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 7c88af38..b1543894 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -481,24 +481,25 @@ exports.handler.addCommands({ exchangePointAndMark: { exec: function (editor, args) { var restoreMarks = []; - editor.forEachSelection({ - exec: function() { - var sel = editor.selection; - if (args.count) { // replace mark and point - var pos = {row: sel.lead.row, column: sel.lead.column}; - restoreMarks.push(pos); - sel.clearSelection(); - sel.moveCursorToPosition(editor.popEmacsMark()); - } else if (sel.isEmpty()) { // move to mark, forget point - var lastMark = editor.popEmacsMark(); - restoreMarks.push(lastMark); - sel.selectToPosition(lastMark); - } else { // just invert selection - sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); - } - } - }); + if (editor.inMultiSelectMode) editor.forEachSelection({exec: doExchange}); + else doExchange(); restoreMarks.reverse().forEach(function(p) { editor.pushEmacsMark(p); }); + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + function doExchange() { + var sel = editor.selection; + if (args.count) { // replace mark and point + var pos = {row: sel.lead.row, column: sel.lead.column}; + restoreMarks.push(pos); + sel.clearSelection(); + sel.moveCursorToPosition(editor.popEmacsMark()); + } else if (sel.isEmpty()) { // move to mark, forget point + var lastMark = editor.popEmacsMark(); + restoreMarks.push(lastMark); + sel.selectToPosition(lastMark); + } else { // just invert selection + sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); + } + } }, readOnly: true, handlesCount: true, From 54d80d79ab723f0b5f040f72d2df9d15c2b4724a Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:49 -0800 Subject: [PATCH 41/53] emacs: make code strict conform --- lib/ace/keyboard/emacs.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index b1543894..272071d1 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -444,10 +444,6 @@ exports.handler.addCommands({ // in multi select mode, ea selection is handled individually if (args && args.count) { - function moveToMark() { - var mark = editor.popEmacsMark(); - mark && editor.moveCursorToPosition(mark); - } if (editor.inMultiSelectMode) editor.forEachSelection({exec: moveToMark}); else moveToMark(); return; @@ -473,6 +469,14 @@ exports.handler.addCommands({ editor.setEmacsMark(rangePositions[rangePositions.length-1]); return; } + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + function moveToMark() { + var mark = editor.popEmacsMark(); + mark && editor.moveCursorToPosition(mark); + } + }, readOnly: true, handlesCount: true, From 0a055cb7259dcc697a0a2a4820293201895c9314 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 21:10:14 -0800 Subject: [PATCH 42/53] isearch: being flexible about whether emacs mode is on or not --- lib/ace/incremental_search.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ace/incremental_search.js b/lib/ace/incremental_search.js index ee74f60d..0f32e0c1 100644 --- a/lib/ace/incremental_search.js +++ b/lib/ace/incremental_search.js @@ -141,7 +141,8 @@ oop.inherits(IncrementalSearch, Search); options.start = this.$currentPos; var session = this.$editor.session, found = this.find(session), - shouldSelect = !!this.$editor.emacsMark(); + shouldSelect = this.$editor.emacsMark ? + !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); 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)); From 8786e17e6b235446d45095be3c9aead8bc17bd61 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 21:23:45 -0800 Subject: [PATCH 43/53] isearch test: ensure multi select --- lib/ace/incremental_search_test.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index 262e09a7..f47e6b4f 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,10 +35,12 @@ 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; @@ -69,6 +71,7 @@ module.exports = { setUp: function() { var session = new EditSession(["abc123", "xyz124"]); editor = new Editor(new MockRenderer(), session); + new MultiSelect(editor); iSearch = new IncrementalSearch(); }, @@ -195,7 +198,7 @@ module.exports = { editor.keyBinding.addKeyboardHandler(emacs.handler); emacs.handler.commands.setMark.exec(editor); iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2');; + iSearch.addString('1'); iSearch.addString('2'); testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); } From 939e0739a7eded9bb9cf92ea697c54d00e799138 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Wed, 5 Nov 2014 11:50:14 -0800 Subject: [PATCH 44/53] adding improvements as suggested by @nightwing --- lib/ace/incremental_search_test.js | 4 ++-- lib/ace/keyboard/emacs.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index f47e6b4f..1d359a9a 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -40,10 +40,11 @@ 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(); @@ -71,7 +72,6 @@ module.exports = { setUp: function() { var session = new EditSession(["abc123", "xyz124"]); editor = new Editor(new MockRenderer(), session); - new MultiSelect(editor); iSearch = new IncrementalSearch(); }, diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 272071d1..674feaaa 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -444,7 +444,7 @@ exports.handler.addCommands({ // in multi select mode, ea selection is handled individually if (args && args.count) { - if (editor.inMultiSelectMode) editor.forEachSelection({exec: moveToMark}); + if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark); else moveToMark(); return; } From 7bb5b305be6d35b8f2322ae53de95152cd77eb62 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:08 -0800 Subject: [PATCH 45/53] isearch: add regexp support --- lib/ace/incremental_search.js | 56 ++++++++++++++++++++++++++++-- lib/ace/incremental_search_test.js | 21 +++++++---- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/lib/ace/incremental_search.js b/lib/ace/incremental_search.js index 88615006..4e7f7bf3 100644 --- a/lib/ace/incremental_search.js +++ b/lib/ace/incremental_search.js @@ -64,6 +64,34 @@ 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) { @@ -140,7 +168,9 @@ oop.inherits(IncrementalSearch, Search); // try to find the next occurence and enable highlighting marker options.start = this.$currentPos; var session = this.$editor.session, - found = this.find(session); + found = this.find(session), + shouldSelect = this.$editor.emacsMark ? + !!this.$editor.emacsMark() : !this.$editor.selection.isEmpty(); if (found) { if (options.backwards) found = Range.fromPoints(found.end, found.start); this.$editor.moveCursorToPosition(found.end); @@ -156,13 +186,21 @@ oop.inherits(IncrementalSearch, Search); this.addString = function(s) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle + s; + if (!isRegExp(needle)) + return needle + s; + var reObj = regExpToObject(needle); + reObj.expression += s; + return objectToRegExp(reObj); }); } this.removeChar = function(c) { return this.highlightAndFindWithNeedle(false, function(needle) { - return needle.length > 0 ? needle.substring(0, needle.length-1) : 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); }); } @@ -189,6 +227,18 @@ oop.inherits(IncrementalSearch, Search); 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 = ''; msg += options.backwards ? 'reverse-' : ''; diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index 262e09a7..c99e9382 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,10 +35,12 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; +var config = require("./config"); 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; @@ -69,6 +71,7 @@ module.exports = { setUp: function() { var session = new EditSession(["abc123", "xyz124"]); editor = new Editor(new MockRenderer(), session); + new MultiSelect(editor); iSearch = new IncrementalSearch(); }, @@ -190,13 +193,17 @@ module.exports = { testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, - "test: extend selection in emacs mark mode" : function() { - var emacs = require('./keyboard/emacs'); - editor.keyBinding.addKeyboardHandler(emacs.handler); - emacs.handler.commands.setMark.exec(editor); - iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2');; - testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); + "test: extend selection in emacs mark mode" : function(next) { + config.loadModule("ace/keyboard/emacs", function(emacs) { + // var emacs = require('./keyboard/emacs'); + editor.keyBinding.addKeyboardHandler(emacs.handler); + emacs.handler.commands.setMark.exec(editor); + iSearch.activate(editor); + iSearch.addString('1'); iSearch.addString('2'); + + testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); + next(); + }); } }; From a93646d2f704f15d759adc8fe0d20be39fc86528 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 13:01:29 -0800 Subject: [PATCH 46/53] isearch: commands searchAsRegExp and selectAllMatches --- .../commands/incremental_search_commands.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/lib/ace/commands/incremental_search_commands.js b/lib/ace/commands/incremental_search_commands.js index 8ef80303..a0a0fe5f 100644 --- a/lib/ace/commands/incremental_search_commands.js +++ b/lib/ace/commands/incremental_search_commands.js @@ -162,6 +162,28 @@ exports.iSearchCommands = [{ exec: function(iSearch) { iSearch.$editor.execCommand('recenterTopBottom'); }, readOnly: true, isIncrementalSearchCommand: true +}, { + 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)); + }, + readOnly: true, + isIncrementalSearchCommand: true +}, { + name: 'searchAsRegExp', + bindKey: 'Alt-r', + exec: function(iSearch) { + iSearch.convertNeedleToRegExp(); + }, + readOnly: true, + isIncrementalSearchCommand: true }]; function IncrementalSearchKeyboardHandler(iSearch) { From 775cdedefb1baeb94410bb5449f5f121c4437ed4 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Tue, 4 Nov 2014 16:00:48 -0800 Subject: [PATCH 47/53] isearch test fix --- lib/ace/incremental_search_test.js | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/ace/incremental_search_test.js b/lib/ace/incremental_search_test.js index c99e9382..991291c5 100644 --- a/lib/ace/incremental_search_test.js +++ b/lib/ace/incremental_search_test.js @@ -35,7 +35,7 @@ if (typeof process !== "undefined") { define(function(require, exports, module) { "use strict"; -var config = require("./config"); +var emacs = require('./keyboard/emacs'); var EditSession = require("./edit_session").EditSession; var Editor = require("./editor").Editor; var MockRenderer = require("./test/mockrenderer").MockRenderer; @@ -193,17 +193,14 @@ module.exports = { testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); }, - "test: extend selection in emacs mark mode" : function(next) { - config.loadModule("ace/keyboard/emacs", function(emacs) { - // var emacs = require('./keyboard/emacs'); - editor.keyBinding.addKeyboardHandler(emacs.handler); - emacs.handler.commands.setMark.exec(editor); - iSearch.activate(editor); - iSearch.addString('1'); iSearch.addString('2'); - - testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); - next(); - }); + "test: extend selection in emacs mark mode" : function() { + var emacs = require('./keyboard/emacs'); + editor.keyBinding.addKeyboardHandler(emacs.handler); + emacs.handler.commands.setMark.exec(editor); + iSearch.activate(editor); + iSearch.addString('1'); iSearch.addString('2'); + + testRanges("Range: [0/0] -> [0/5]", [editor.getSelectionRange()], "sel range"); } }; From 072dcb1c11aee9775966d5c85d510a89e8439c05 Mon Sep 17 00:00:00 2001 From: nightwing Date: Thu, 6 Nov 2014 20:41:25 +0400 Subject: [PATCH 48/53] fix tripple brace highlighting in handlebars mode --- demo/kitchen-sink/docs/handlebars.hbs | 2 +- lib/ace/mode/_test/tokens_cirru.json | 267 +++++++++++++++++++++ lib/ace/mode/_test/tokens_elixir.json | 196 +++++++++++++++ lib/ace/mode/_test/tokens_handlebars.json | 4 +- lib/ace/mode/handlebars.js | 2 +- lib/ace/mode/handlebars_highlight_rules.js | 18 +- lib/ace/snippets/elixir.js | 7 + lib/ace/snippets/elixir.snippets | 0 8 files changed, 483 insertions(+), 13 deletions(-) create mode 100644 lib/ace/mode/_test/tokens_cirru.json create mode 100644 lib/ace/mode/_test/tokens_elixir.json create mode 100644 lib/ace/snippets/elixir.js create mode 100644 lib/ace/snippets/elixir.snippets diff --git a/demo/kitchen-sink/docs/handlebars.hbs b/demo/kitchen-sink/docs/handlebars.hbs index 1cdf786e..bb096a1a 100644 --- a/demo/kitchen-sink/docs/handlebars.hbs +++ b/demo/kitchen-sink/docs/handlebars.hbs @@ -3,6 +3,6 @@
    {{#each comments}}

    {{title}}

    -
    {{body}}
    +
    {{{body}}}
    {{/each}}
    diff --git a/lib/ace/mode/_test/tokens_cirru.json b/lib/ace/mode/_test/tokens_cirru.json new file mode 100644 index 00000000..de4852e6 --- /dev/null +++ b/lib/ace/mode/_test/tokens_cirru.json @@ -0,0 +1,267 @@ +[[ + "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_elixir.json b/lib/ace/mode/_test/tokens_elixir.json new file mode 100644 index 00000000..cbbe1fee --- /dev/null +++ b/lib/ace/mode/_test/tokens_elixir.json @@ -0,0 +1,196 @@ +[[ + "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_handlebars.json b/lib/ace/mode/_test/tokens_handlebars.json index ef8cb82a..1ec79139 100644 --- a/lib/ace/mode/_test/tokens_handlebars.json +++ b/lib/ace/mode/_test/tokens_handlebars.json @@ -59,9 +59,9 @@ ["meta.tag.punctuation.tag-open.xml","<"], ["meta.tag.tag-name.xml","div"], ["meta.tag.punctuation.tag-close.xml",">"], - ["storage.type.start","{{"], + ["support.function","{{{"], ["variable.parameter","body"], - ["storage.type.end","}}"], + ["support.function","}}}"], ["meta.tag.punctuation.end-tag-open.xml",""] diff --git a/lib/ace/mode/handlebars.js b/lib/ace/mode/handlebars.js index 38af7e5c..3f2e7179 100644 --- a/lib/ace/mode/handlebars.js +++ b/lib/ace/mode/handlebars.js @@ -21,7 +21,7 @@ var Mode = function() { oop.inherits(Mode, HtmlMode); (function() { - + this.blockComment = {start: "{!--", end: "--}"}; this.$id = "ace/mode/handlebars"; }).call(Mode.prototype); diff --git a/lib/ace/mode/handlebars_highlight_rules.js b/lib/ace/mode/handlebars_highlight_rules.js index c264afc1..f91a48ec 100644 --- a/lib/ace/mode/handlebars_highlight_rules.js +++ b/lib/ace/mode/handlebars_highlight_rules.js @@ -15,7 +15,7 @@ var HandlebarsHighlightRules = function() { var hbs = { regex : "(?={{)", push : "handlebars" - } + }; for (var key in this.$rules) { this.$rules[key].unshift(hbs); } @@ -40,22 +40,22 @@ var HandlebarsHighlightRules = function() { defaultToken : "comment" }] }, { - token : "storage.type.start", // begin section - regex : "{{[#\\^/&]?", + token : "support.function", // unescaped variable + regex : "{{{", push : [{ - token : "storage.type.end", - regex : "}}", + token : "support.function", + regex : "}}}", next : pop2 }, { token : "variable.parameter", regex : "[a-zA-Z_$][a-zA-Z0-9_$]*" }] }, { - token : "support.function", // unescaped variable - regex : "{{{", + token : "storage.type.start", // begin section + regex : "{{[#\\^/&]?", push : [{ - token : "support.function", - regex : "}}}", + token : "storage.type.end", + regex : "}}", next : pop2 }, { token : "variable.parameter", diff --git a/lib/ace/snippets/elixir.js b/lib/ace/snippets/elixir.js new file mode 100644 index 00000000..359d9103 --- /dev/null +++ b/lib/ace/snippets/elixir.js @@ -0,0 +1,7 @@ +define(function(require, exports, module) { +"use strict"; + +exports.snippetText = require("../requirejs/text!./.snippets"); +exports.scope = ""; + +}); diff --git a/lib/ace/snippets/elixir.snippets b/lib/ace/snippets/elixir.snippets new file mode 100644 index 00000000..e69de29b From e83252130c93057bf5ce4b01c9547dc362c1dde4 Mon Sep 17 00:00:00 2001 From: Robert Krahn Date: Thu, 6 Nov 2014 23:27:54 -0800 Subject: [PATCH 49/53] emacs: improved multi selection handling for emacs mark --- build | 2 +- lib/ace/keyboard/emacs.js | 57 +++++++++++++---------- lib/ace/keyboard/emacs_test.js | 83 +++++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 25 deletions(-) diff --git a/build b/build index 17c02716..fc9d2cae 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit 17c02716b7f116c7920f8ef07c8c2b0e20d77ec0 +Subproject commit fc9d2cae9fe8e6e95e74c86a31d21caadd8f9f39 diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 674feaaa..2b6bd2c4 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -125,6 +125,24 @@ exports.handler.attach = function(editor) { 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); editor.on("changeSession", $kbSessionChange); editor.renderer.screenToTextCoordinates = screenToTextBlockCoordinates; @@ -446,6 +464,7 @@ exports.handler.addCommands({ if (args && args.count) { if (editor.inMultiSelectMode) editor.forEachSelection(moveToMark); else moveToMark(); + moveToMark(); return; } @@ -465,7 +484,7 @@ exports.handler.addCommands({ } if (!mark) { - rangePositions.slice(0,-1).forEach(function(pos) { editor.pushEmacsMark(pos); }); + rangePositions.forEach(function(pos) { editor.pushEmacsMark(pos); }); editor.setEmacsMark(rangePositions[rangePositions.length-1]); return; } @@ -479,30 +498,22 @@ exports.handler.addCommands({ }, readOnly: true, - handlesCount: true, - multiSelectAction: "forEach" + handlesCount: true }, exchangePointAndMark: { - exec: function (editor, args) { - var restoreMarks = []; - if (editor.inMultiSelectMode) editor.forEachSelection({exec: doExchange}); - else doExchange(); - restoreMarks.reverse().forEach(function(p) { editor.pushEmacsMark(p); }); - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - function doExchange() { - var sel = editor.selection; - if (args.count) { // replace mark and point - var pos = {row: sel.lead.row, column: sel.lead.column}; - restoreMarks.push(pos); - sel.clearSelection(); - sel.moveCursorToPosition(editor.popEmacsMark()); - } else if (sel.isEmpty()) { // move to mark, forget point - var lastMark = editor.popEmacsMark(); - restoreMarks.push(lastMark); - sel.selectToPosition(lastMark); - } else { // just invert selection - sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); - } + exec: function exchangePointAndMark$exec(editor, args) { + var sel = editor.selection; + if (!args.count && !sel.isEmpty()) { // just invert selection + sel.setSelectionRange(sel.getRange(), !sel.isBackwards()); + 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()); } }, readOnly: true, diff --git a/lib/ace/keyboard/emacs_test.js b/lib/ace/keyboard/emacs_test.js index d1aba564..09693156 100644 --- a/lib/ace/keyboard/emacs_test.js +++ b/lib/ace/keyboard/emacs_test.js @@ -35,17 +35,29 @@ 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; + editor, sel; 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 = { @@ -62,6 +74,75 @@ module.exports = { editor.selectAll(); editor.execCommand('keyboardQuit'); assert.ok(editor.selection.isEmpty(), 'selection non-empty'); + }, + +// this.aceEditor.getSelectedText() +// this.aceEditor.selection.getAllRanges() +// lively.ide.ace.require("ace/range").Range.fromPoints(start, end) + "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)); } }; From d09740f4947ef64c37bb2a36af34c786ff552726 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 8 Nov 2014 15:57:23 +0400 Subject: [PATCH 50/53] fix emacs universal argument --- lib/ace/ext/statusbar.js | 5 ++--- lib/ace/keyboard/emacs.js | 31 +++++++++++++++++++------------ lib/ace/keyboard/emacs_test.js | 3 --- lib/ace/keyboard/keybinding.js | 10 +++++++++- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/ace/ext/statusbar.js b/lib/ace/ext/statusbar.js index 666febfa..5e5b0572 100644 --- a/lib/ace/ext/statusbar.js +++ b/lib/ace/ext/statusbar.js @@ -28,9 +28,8 @@ var StatusBar = function(editor, parentNode) { str && status.push(str, separator || "|"); } - if (editor.$vimModeHandler) - add(editor.$vimModeHandler.getStatusText()); - else if (editor.commands.recording) + add(editor.keyBinding.getStatusText(editor)); + if (editor.commands.recording) add("REC"); var c = editor.selection.lead; diff --git a/lib/ace/keyboard/emacs.js b/lib/ace/keyboard/emacs.js index 2b6bd2c4..945eddf3 100644 --- a/lib/ace/keyboard/emacs.js +++ b/lib/ace/keyboard/emacs.js @@ -164,6 +164,7 @@ 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) { @@ -205,7 +206,7 @@ exports.handler.onCopy = function(e, editor) { if (editor.$handlesEmacsOnCopy) return; editor.$handlesEmacsOnCopy = true; exports.handler.commands.killRingSave.exec(editor); - delete editor.$handlesEmacsOnCopy; + editor.$handlesEmacsOnCopy = false; }; exports.handler.onPaste = function(e, editor) { @@ -238,12 +239,22 @@ exports.handler.bindKey = function(key, command) { }, 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(); @@ -254,24 +265,17 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { } } - if (key == "\x00") return undefined; - var modifier = eMods[hashId]; // CTRL + number / universalArgument for setting data.count - if (modifier == "c-" || data.universalArgument) { - var prevCount = String(data.count || 0); + if (modifier == "c-" || data.count) { var count = parseInt(key[key.length - 1]); if (typeof count === 'number' && !isNaN(count)) { - data.count = parseInt(prevCount + count); + data.count = Math.max(data.count, 0) || 0; + data.count = 10 * data.count + 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 @@ -293,7 +297,9 @@ exports.handler.handleKeyboard = function(data, hashId, key, keyCode) { if (command === "null") return {command: "null"}; if (command === "universalArgument") { - data.universalArgument = true; + // if no number pressed emacs repeats action 4 times. + // minus sign is needed to allow next keypress to replace it + data.count = -4; return {command: "null"}; } @@ -607,6 +613,7 @@ exports.handler.addCommands({ 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 09693156..3ba5efaa 100644 --- a/lib/ace/keyboard/emacs_test.js +++ b/lib/ace/keyboard/emacs_test.js @@ -76,9 +76,6 @@ module.exports = { assert.ok(editor.selection.isEmpty(), 'selection non-empty'); }, -// this.aceEditor.getSelectedText() -// this.aceEditor.selection.getAllRanges() -// lively.ide.ace.require("ace/range").Range.fromPoints(start, end) "test: exchangePointAndMark without mark set": function() { initEditor('foo'); sel.setRange(Range.fromPoints({row: 0, column: 1}, {row: 0, column: 3})); diff --git a/lib/ace/keyboard/keybinding.js b/lib/ace/keyboard/keybinding.js index c43d7930..cddf0666 100644 --- a/lib/ace/keyboard/keybinding.js +++ b/lib/ace/keyboard/keybinding.js @@ -89,8 +89,16 @@ 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; From a4d831f47410e62dd2183054170a6d054f4c5380 Mon Sep 17 00:00:00 2001 From: nightwing Date: Sat, 8 Nov 2014 20:56:18 +0400 Subject: [PATCH 51/53] add more users --- doc/site/images/lws-logo.png | Bin 17695 -> 0 bytes index.html | 145 +++++++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 25 deletions(-) delete mode 100644 doc/site/images/lws-logo.png diff --git a/doc/site/images/lws-logo.png b/doc/site/images/lws-logo.png deleted file mode 100644 index 402b332cc7b95cb778809ef2bf8f4cebbed6d8f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17695 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 ePvQsn`2PW~6(s>*BWVx-0000RStudio
  • - - Application Craft + + Zed
  • - - StackEdit + + Tedit
  • @@ -796,8 +795,9 @@ if (match) { Plunker
  • - - Zed + + Application Craft
  • Ideone.com
  • - - Pixie +
    + + Lively Web
  • Evaluzio
  • - +
    CodeHelper
  • @@ -949,15 +954,13 @@ if (match) { Slim Text
  • - Decor
  • - - Divshot + + Papeeria