toggle comment functionality (Meta-7)
This commit is contained in:
parent
29435328f3
commit
7399cc94e3
12 changed files with 266 additions and 40 deletions
|
|
@ -9,11 +9,24 @@
|
||||||
|
|
||||||
<style type="text/css" media="screen">
|
<style type="text/css" media="screen">
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
top: 0px;
|
top: 30px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#controls {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
border: 1px solid black;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -39,21 +52,51 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
<table id="controls">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<label for="mode">Mode:</label>
|
||||||
|
<select id="mode" size="1">
|
||||||
|
<option value="text">Plain Text</option>
|
||||||
|
<option value="javascript">JavaScript</option>
|
||||||
|
<option value="xml">XML</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<div id="container">
|
<div id="container">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" charset="utf-8">
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
|
||||||
|
var modeEl = document.getElementById("mode");
|
||||||
|
modeEl.onchange = function() {
|
||||||
|
editor.setMode(getMode());
|
||||||
|
};
|
||||||
|
|
||||||
|
var modes = {
|
||||||
|
text: new ace.mode.Text(),
|
||||||
|
xml: new ace.mode.Xml(),
|
||||||
|
javascript: new ace.mode.JavaScript()
|
||||||
|
};
|
||||||
|
|
||||||
|
function getMode() {
|
||||||
|
return modes[modeEl.value];
|
||||||
|
}
|
||||||
|
|
||||||
var container = document.getElementById("container");
|
var container = document.getElementById("container");
|
||||||
var editor = new ace.Editor(
|
var editor = new ace.Editor(
|
||||||
new ace.VirtualRenderer(container),
|
new ace.VirtualRenderer(container),
|
||||||
new ace.TextDocument("Juhu Kinners"),
|
new ace.TextDocument("Juhu Kinners"),
|
||||||
new ace.mode.JavaScript()
|
getMode()
|
||||||
);
|
);
|
||||||
|
|
||||||
window.onresize = function() {
|
window.onresize = function() {
|
||||||
editor.resize();
|
editor.resize();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,6 @@ load:
|
||||||
- src/mode/Text.js
|
- src/mode/Text.js
|
||||||
- src/mode/*.js
|
- src/mode/*.js
|
||||||
- src/*.js
|
- src/*.js
|
||||||
- test/*.js
|
|
||||||
|
- test/*.js
|
||||||
|
- test/mode/*.js
|
||||||
|
|
@ -47,6 +47,13 @@ ace.BackgroundTokenizer = function(tokenizer, onUpdate, onComplete) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ace.BackgroundTokenizer.prototype.setTokenizer = function(tokenizer) {
|
||||||
|
this.tokenizer = tokenizer;
|
||||||
|
this.lines = [];
|
||||||
|
|
||||||
|
this.start(0);
|
||||||
|
};
|
||||||
|
|
||||||
ace.BackgroundTokenizer.prototype.setLines = function(textLines) {
|
ace.BackgroundTokenizer.prototype.setLines = function(textLines) {
|
||||||
this.textLines = textLines;
|
this.textLines = textLines;
|
||||||
this.lines = [];
|
this.lines = [];
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ ace.Editor = function(renderer, doc, mode) {
|
||||||
var container = renderer.getContainerElement();
|
var container = renderer.getContainerElement();
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
|
|
||||||
this.setDocument(doc || new ace.TextDocument(""));
|
|
||||||
this.setMode(mode || new ace.mode.Text());
|
this.setMode(mode || new ace.mode.Text());
|
||||||
|
this.setDocument(doc || new ace.TextDocument(""));
|
||||||
|
|
||||||
this.textInput = new ace.TextInput(container, this);
|
this.textInput = new ace.TextInput(container, this);
|
||||||
new ace.KeyBinding(container, this);
|
new ace.KeyBinding(container, this);
|
||||||
|
|
@ -39,20 +39,23 @@ ace.Editor.prototype.setDocument = function(doc) {
|
||||||
this.doc = doc;
|
this.doc = doc;
|
||||||
doc.addChangeListener(ace.bind(this.onDocumentChange, this));
|
doc.addChangeListener(ace.bind(this.onDocumentChange, this));
|
||||||
this.renderer.setDocument(doc);
|
this.renderer.setDocument(doc);
|
||||||
|
|
||||||
|
this.bgTokenizer.setLines(this.doc.lines);
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.setMode = function(mode) {
|
ace.Editor.prototype.setMode = function(mode) {
|
||||||
// TODO: mode change is not yet supported
|
|
||||||
if (this.mode) {
|
|
||||||
throw new Error("TODO: mode change is not yet supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
|
var tokenizer = mode.getTokenizer();
|
||||||
|
|
||||||
this.tokenizer = new ace.BackgroundTokenizer(mode.getTokenizer(), ace.bind(this.onTokenizerUpdate, this));
|
if (!this.bgTokenizer) {
|
||||||
|
var onUpdate = ace.bind(this.onTokenizerUpdate, this);
|
||||||
|
this.bgTokenizer = new ace.BackgroundTokenizer(tokenizer, onUpdate);
|
||||||
|
} else {
|
||||||
|
this.bgTokenizer.setTokenizer(tokenizer);
|
||||||
|
}
|
||||||
|
|
||||||
this.tokenizer.setLines(this.doc.lines);
|
this.renderer.setTokenizer(this.bgTokenizer);
|
||||||
this.renderer.setTokenizer(this.tokenizer);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.resize = function()
|
ace.Editor.prototype.resize = function()
|
||||||
|
|
@ -109,7 +112,7 @@ ace.Editor.prototype.onBlur = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.onDocumentChange = function(startRow, endRow) {
|
ace.Editor.prototype.onDocumentChange = function(startRow, endRow) {
|
||||||
this.tokenizer.start(startRow);
|
this.bgTokenizer.start(startRow);
|
||||||
this.renderer.updateLines(startRow, endRow);
|
this.renderer.updateLines(startRow, endRow);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -259,35 +262,30 @@ ace.Editor.prototype.removeLine = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.blockIndent = function(indentString) {
|
ace.Editor.prototype.blockIndent = function(indentString) {
|
||||||
if (!this.hasSelection()) {
|
if (!this.hasSelection()) return;
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
var range = this.getSelectionRange();
|
|
||||||
|
|
||||||
var indentString = indentString || " ";
|
var indentString = indentString || " ";
|
||||||
this.doc.indentRows(range, indentString);
|
var addedColumns = this.doc.indentRows(this.getSelectionRange(), indentString);
|
||||||
|
|
||||||
this.setSelectionAnchor(range.start.row, range.start.column + indentString.length);
|
this.shiftSelection(addedColumns);
|
||||||
this._moveSelection(function() {
|
|
||||||
this.moveCursorTo(range.end.row, range.end.column + indentString.length);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.blockOutdent = function(indentString) {
|
ace.Editor.prototype.blockOutdent = function(indentString) {
|
||||||
if (!this.hasSelection()) {
|
if (!this.hasSelection()) return;
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
var range = this.getSelectionRange();
|
|
||||||
|
|
||||||
var indentString = indentString || " ";
|
var indentString = indentString || " ";
|
||||||
var removedColumns = this.doc.outdentRows(range, indentString);
|
var addedColumns = this.doc.outdentRows(this.getSelectionRange(), indentString);
|
||||||
|
|
||||||
this.setSelectionAnchor(range.start.row, range.start.column - removedColumns);
|
this.shiftSelection(addedColumns);
|
||||||
this._moveSelection(function() {
|
};
|
||||||
this.moveCursorTo(range.end.row, range.end.column - removedColumns);
|
|
||||||
});
|
ace.Editor.prototype.toggleCommentLines = function() {
|
||||||
|
if (!this.hasSelection()) return;
|
||||||
|
|
||||||
|
var selection = this.getSelectionRange();
|
||||||
|
var addedColumns = this.mode.toggleCommentLines(this.doc, selection);
|
||||||
|
|
||||||
|
this.shiftSelection(addedColumns);
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.onCompositionStart = function() {
|
ace.Editor.prototype.onCompositionStart = function() {
|
||||||
|
|
@ -591,6 +589,40 @@ ace.Editor.prototype.setSelectionAnchor = function(row, column) {
|
||||||
this.selectionLead = null;
|
this.selectionLead = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ace.Editor.prototype.getSelectionAnchor = function() {
|
||||||
|
if (this.selectionAnchor) {
|
||||||
|
return {
|
||||||
|
row: this.selectionAnchor.row,
|
||||||
|
column: this.selectionAnchor.column
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ace.Editor.prototype.getSelectionLead = function() {
|
||||||
|
if (this.selectionLead) {
|
||||||
|
return {
|
||||||
|
row: this.selectionLead.row,
|
||||||
|
column: this.selectionLead.column
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ace.Editor.prototype.shiftSelection = function(columns) {
|
||||||
|
if (!this.hasSelection()) return;
|
||||||
|
|
||||||
|
var anchor = this.getSelectionAnchor();
|
||||||
|
var lead = this.getSelectionLead();
|
||||||
|
|
||||||
|
this.setSelectionAnchor(anchor.row, anchor.column + columns);
|
||||||
|
this._moveSelection(function() {
|
||||||
|
this.moveCursorTo(lead.row, lead.column + columns);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
ace.Editor.prototype.getSelectionRange = function() {
|
ace.Editor.prototype.getSelectionRange = function() {
|
||||||
var anchor = this.selectionAnchor;
|
var anchor = this.selectionAnchor;
|
||||||
var lead = this.selectionLead;
|
var lead = this.selectionLead;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ var keys = {
|
||||||
TAB : 9,
|
TAB : 9,
|
||||||
A : 65,
|
A : 65,
|
||||||
D: 68,
|
D: 68,
|
||||||
L: 76
|
L: 76,
|
||||||
|
"7": 55
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.KeyBinding = function(element, host) {
|
ace.KeyBinding = function(element, host) {
|
||||||
|
|
@ -48,6 +49,13 @@ ace.KeyBinding = function(element, host) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case keys["7"]:
|
||||||
|
if (e.metaKey) {
|
||||||
|
host.toggleCommentLines();
|
||||||
|
return ace.stopEvent(e);
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
case keys.UP:
|
case keys.UP:
|
||||||
if (e.metaKey && e.shiftKey) {
|
if (e.metaKey && e.shiftKey) {
|
||||||
host.selectFileStart();
|
host.selectFileStart();
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ ace.TextDocument.prototype.getTextRange = function(range) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ace.TextDocument.prototype.getLines = function(firstRow, lastRow) {
|
||||||
|
return this.lines.slice(firstRow, lastRow+1);
|
||||||
|
};
|
||||||
|
|
||||||
ace.TextDocument.prototype.findMatchingBracket = function(position) {
|
ace.TextDocument.prototype.findMatchingBracket = function(position) {
|
||||||
if (position.column == 0) return null;
|
if (position.column == 0) return null;
|
||||||
|
|
||||||
|
|
@ -279,6 +283,7 @@ ace.TextDocument.prototype.indentRows = function(range, indentString) {
|
||||||
this.lines[i] = indentString + this.getLine(i);
|
this.lines[i] = indentString + this.getLine(i);
|
||||||
}
|
}
|
||||||
this.fireChangeEvent(range.start.row, range.end.row);
|
this.fireChangeEvent(range.start.row, range.end.row);
|
||||||
|
return indentString.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.TextDocument.prototype.outdentRows = function(range, indentString) {
|
ace.TextDocument.prototype.outdentRows = function(range, indentString) {
|
||||||
|
|
@ -295,5 +300,5 @@ ace.TextDocument.prototype.outdentRows = function(range, indentString) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fireChangeEvent(range.start.row, range.end.row);
|
this.fireChangeEvent(range.start.row, range.end.row);
|
||||||
return outdentLength;
|
return -outdentLength;
|
||||||
};
|
};
|
||||||
|
|
@ -5,3 +5,10 @@ ace.mode.JavaScript = function() {
|
||||||
};
|
};
|
||||||
ace.inherits(ace.mode.JavaScript, ace.mode.Text);
|
ace.inherits(ace.mode.JavaScript, ace.mode.Text);
|
||||||
|
|
||||||
|
ace.mode.JavaScript.prototype.toggleCommentLines = function(doc, range) {
|
||||||
|
var addedRows = doc.outdentRows(range, "//");
|
||||||
|
if (addedRows == 0) {
|
||||||
|
var addedRows = doc.indentRows(range, "//");
|
||||||
|
};
|
||||||
|
return addedRows;
|
||||||
|
};
|
||||||
|
|
@ -1,9 +1,19 @@
|
||||||
ace.provide("ace.mode.Text");
|
ace.provide("ace.mode.Text");
|
||||||
|
|
||||||
ace.mode.Text = function() {
|
ace.mode.Text = function() {
|
||||||
this.$tokenizer = new ace.Tokenizer({});
|
var rules = {
|
||||||
|
"start" : [ {
|
||||||
|
token : "text",
|
||||||
|
regex : ".+"
|
||||||
|
} ]
|
||||||
|
};
|
||||||
|
this.$tokenizer = new ace.Tokenizer(rules);
|
||||||
};
|
};
|
||||||
|
|
||||||
ace.mode.Text.prototype.getTokenizer = function() {
|
ace.mode.Text.prototype.getTokenizer = function() {
|
||||||
return this.$tokenizer;
|
return this.$tokenizer;
|
||||||
|
};
|
||||||
|
|
||||||
|
ace.mode.Text.prototype.toggleCommentLines = function(doc, range) {
|
||||||
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
ace.provide("ace.mode.Xml");
|
ace.provide("ace.mode.Xml");
|
||||||
|
|
||||||
ace.mode.Xml = function() {
|
ace.mode.Xml = function() {
|
||||||
this.$tokenizer = new Tokenizer(new ace.mode.XmlHighlightRules().getRules());
|
this.$tokenizer = new ace.Tokenizer(new ace.mode.XmlHighlightRules().getRules());
|
||||||
};
|
};
|
||||||
ace.inherits(ace.mode.Xml, ace.mode.Text);
|
ace.inherits(ace.mode.Xml, ace.mode.Text);
|
||||||
|
|
|
||||||
|
|
@ -73,5 +73,39 @@ var TextEditTest = TestCase("TextEditTest",
|
||||||
var selection = editor.getSelectionRange();
|
var selection = editor.getSelectionRange();
|
||||||
assertPosition(0, 1, selection.start);
|
assertPosition(0, 1, selection.start);
|
||||||
assertPosition(2, 1, selection.end);
|
assertPosition(2, 1, selection.end);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: comment lines should perserve selection" : function() {
|
||||||
|
var doc = new ace.TextDocument([" abc", "cde"].join("\n"));
|
||||||
|
var editor = new ace.Editor(new MockRenderer(), doc, new ace.mode.JavaScript());
|
||||||
|
|
||||||
|
editor.moveCursorTo(0, 2);
|
||||||
|
editor.selectDown();
|
||||||
|
|
||||||
|
editor.toggleCommentLines();
|
||||||
|
|
||||||
|
assertEquals(["// abc", "//cde"].join("\n"), doc.toString());
|
||||||
|
|
||||||
|
var selection = editor.getSelectionRange();
|
||||||
|
assertPosition(0, 4, selection.start);
|
||||||
|
assertPosition(1, 4, selection.end);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: uncomment lines should perserve selection" : function() {
|
||||||
|
var doc = new ace.TextDocument(["// abc", "//cde"].join("\n"));
|
||||||
|
var editor = new ace.Editor(new MockRenderer(), doc, new ace.mode.JavaScript());
|
||||||
|
|
||||||
|
editor.moveCursorTo(0, 1);
|
||||||
|
editor.selectDown();
|
||||||
|
editor.selectRight();
|
||||||
|
editor.selectRight();
|
||||||
|
|
||||||
|
editor.toggleCommentLines();
|
||||||
|
|
||||||
|
assertEquals([" abc", "cde"].join("\n"), doc.toString());
|
||||||
|
|
||||||
|
var selection = editor.getSelectionRange();
|
||||||
|
assertPosition(0, 0, selection.start);
|
||||||
|
assertPosition(1, 1, selection.end);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
51
test/mode/JavaScriptTest.js
Normal file
51
test/mode/JavaScriptTest.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
var JavaScriptTest = new TestCase("mode.JavaScriptTest", {
|
||||||
|
|
||||||
|
setUp : function() {
|
||||||
|
this.mode = new ace.mode.JavaScript();
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: getTokenizer() (smoke test)" : function() {
|
||||||
|
var tokenizer = this.mode.getTokenizer();
|
||||||
|
|
||||||
|
assertTrue(tokenizer instanceof ace.Tokenizer);
|
||||||
|
|
||||||
|
var tokens = tokenizer.getLineTokens("'juhu'", "start").tokens;
|
||||||
|
assertEquals("string", tokens[0].type);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: toggle comment lines should prepend '//' to each line" : function() {
|
||||||
|
var doc = new ace.TextDocument([" abc", "cde", "fg"].join("\n"));
|
||||||
|
|
||||||
|
var range = {
|
||||||
|
start: {row: 0, column: 3},
|
||||||
|
end: {row: 1, column: 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
var comment = this.mode.toggleCommentLines(doc, range);
|
||||||
|
assertEquals(["// abc", "//cde", "fg"].join("\n"), doc.toString());
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: toggle comment on commented lines should remove leading '//' chars" : function() {
|
||||||
|
var doc = new ace.TextDocument(["// abc", "//cde", "fg"].join("\n"));
|
||||||
|
|
||||||
|
var range = {
|
||||||
|
start: {row: 0, column: 3},
|
||||||
|
end: {row: 1, column: 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
var comment = this.mode.toggleCommentLines(doc, range);
|
||||||
|
assertEquals([" abc", "cde", "fg"].join("\n"), doc.toString());
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: toggle comment on multiple lines with one commented line prepend '//' to each line" : function() {
|
||||||
|
var doc = new ace.TextDocument(["// abc", "//cde", "fg"].join("\n"));
|
||||||
|
|
||||||
|
var range = {
|
||||||
|
start: {row: 0, column: 3},
|
||||||
|
end: {row: 2, column: 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
var comment = this.mode.toggleCommentLines(doc, range);
|
||||||
|
assertEquals(["//// abc", "////cde", "//fg"].join("\n"), doc.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
27
test/mode/XmlTest.js
Normal file
27
test/mode/XmlTest.js
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
var XmlTest = new TestCase("mode.XmlTest", {
|
||||||
|
|
||||||
|
setUp : function() {
|
||||||
|
this.mode = new ace.mode.Xml();
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: getTokenizer() (smoke test)" : function() {
|
||||||
|
var tokenizer = this.mode.getTokenizer();
|
||||||
|
|
||||||
|
assertTrue(tokenizer instanceof ace.Tokenizer);
|
||||||
|
|
||||||
|
var tokens = tokenizer.getLineTokens("<juhu>", "start").tokens;
|
||||||
|
assertEquals("keyword", tokens[1].type);
|
||||||
|
},
|
||||||
|
|
||||||
|
"test: toggle comment lines should not do anything" : function() {
|
||||||
|
var doc = new ace.TextDocument([" abc", "cde", "fg"].join("\n"));
|
||||||
|
|
||||||
|
var range = {
|
||||||
|
start: {row: 0, column: 3},
|
||||||
|
end: {row: 1, column: 1}
|
||||||
|
};
|
||||||
|
|
||||||
|
var comment = this.mode.toggleCommentLines(doc, range);
|
||||||
|
assertEquals([" abc", "cde", "fg"].join("\n"), doc.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue