Merge branch 'master' of https://github.com/ajaxorg/ace
Conflicts: lib/ace/commands/default_commands.js lib/ace/edit_session.js
This commit is contained in:
commit
d80f0fe66e
9 changed files with 257 additions and 182 deletions
|
|
@ -301,6 +301,10 @@ exports.launch = function(env) {
|
||||||
env.editor.renderer.setHScrollBarAlwaysVisible(checked);
|
env.editor.renderer.setHScrollBarAlwaysVisible(checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bindCheckbox("soft_tab", function(checked) {
|
||||||
|
env.editor.getSession().setUseSoftTabs(checked);
|
||||||
|
});
|
||||||
|
|
||||||
function bindCheckbox(id, callback) {
|
function bindCheckbox(id, callback) {
|
||||||
var el = document.getElementById(id);
|
var el = document.getElementById(id);
|
||||||
var onCheck = function() {
|
var onCheck = function() {
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<label for="show_hidden">Show Invisibles</label>
|
<label for="show_hidden">Show Invisibles</label>
|
||||||
<input type="checkbox" name="show_hidden" id="show_hidden">
|
<input type="checkbox" name="show_hidden" id="show_hidden" checked>
|
||||||
</td>
|
</td>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<label for="show_hscroll">Persistent HScroll</label>
|
<label for="show_hscroll">Persistent HScroll</label>
|
||||||
|
|
@ -128,6 +128,10 @@
|
||||||
<label for="show_print_margin">Show Print Margin</label>
|
<label for="show_print_margin">Show Print Margin</label>
|
||||||
<input type="checkbox" id="show_print_margin" checked>
|
<input type="checkbox" id="show_print_margin" checked>
|
||||||
</td>
|
</td>
|
||||||
|
<td align="right">
|
||||||
|
<label for="soft_tab">Use Soft Tab:</label>
|
||||||
|
<input type="checkbox" id="soft_tab" checked>
|
||||||
|
</td>
|
||||||
<td align="right">
|
<td align="right">
|
||||||
<label for="highlight_selected_word">Highlight selected word</label>
|
<label for="highlight_selected_word">Highlight selected word</label>
|
||||||
<input type="checkbox" id="highlight_selected_word" checked>
|
<input type="checkbox" id="highlight_selected_word" checked>
|
||||||
|
|
@ -144,7 +148,7 @@
|
||||||
<script type="text/editor" id="jstext">function foo(items) {
|
<script type="text/editor" id="jstext">function foo(items) {
|
||||||
for (var i=0; i<items.length; i++) {
|
for (var i=0; i<items.length; i++) {
|
||||||
alert(items[i] + "juhu");
|
alert(items[i] + "juhu");
|
||||||
}
|
} // Real Tab.
|
||||||
}
|
}
|
||||||
// A magic character: >> ぁ <<
|
// A magic character: >> ぁ <<
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -389,7 +389,7 @@ exports.startup = function() {
|
||||||
});
|
});
|
||||||
gcli.addCommand({
|
gcli.addCommand({
|
||||||
name: "centerselection",
|
name: "centerselection",
|
||||||
bindKey: bindKey("Ctrl-L", "Ctrl-L"),
|
bindKey: bindKey(null, "Ctrl-L"),
|
||||||
exec: function(env, args, request) { env.editor.centerSelection(); }
|
exec: function(env, args, request) { env.editor.centerSelection(); }
|
||||||
});
|
});
|
||||||
gcli.addCommand({
|
gcli.addCommand({
|
||||||
|
|
|
||||||
|
|
@ -233,14 +233,14 @@ var EditSession = function(text, mode) {
|
||||||
renderer: typeof type == "function" ? type : null,
|
renderer: typeof type == "function" ? type : null,
|
||||||
clazz : clazz,
|
clazz : clazz,
|
||||||
inFront: !!inFront
|
inFront: !!inFront
|
||||||
}
|
};
|
||||||
|
|
||||||
if (inFront) {
|
if (inFront) {
|
||||||
this.$frontMarkers[id] = marker;
|
this.$frontMarkers[id] = marker;
|
||||||
this._dispatchEvent("changeFrontMarker")
|
this._dispatchEvent("changeFrontMarker");
|
||||||
} else {
|
} else {
|
||||||
this.$backMarkers[id] = marker;
|
this.$backMarkers[id] = marker;
|
||||||
this._dispatchEvent("changeBackMarker")
|
this._dispatchEvent("changeBackMarker");
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
|
|
@ -414,17 +414,13 @@ var EditSession = function(text, mode) {
|
||||||
var lines = this.doc.getAllLines();
|
var lines = this.doc.getAllLines();
|
||||||
var longestLine = 0;
|
var longestLine = 0;
|
||||||
var longestScreenLine = 0;
|
var longestScreenLine = 0;
|
||||||
var tabSize = this.getTabSize();
|
|
||||||
|
|
||||||
for ( var i = 0; i < lines.length; i++) {
|
for ( var i = 0; i < lines.length; i++) {
|
||||||
var len = lines[i].length;
|
var line = lines[i],
|
||||||
|
len = line.length,
|
||||||
|
screenLen = this.$getStringScreenWidth(line);
|
||||||
longestLine = Math.max(longestLine, len);
|
longestLine = Math.max(longestLine, len);
|
||||||
|
longestScreenLine = Math.max(longestScreenLine, screenLen);
|
||||||
lines[i].replace(/\t/g, function(m) {
|
|
||||||
len += tabSize-1;
|
|
||||||
return m;
|
|
||||||
});
|
|
||||||
longestScreenLine = Math.max(longestScreenLine, len);
|
|
||||||
}
|
}
|
||||||
this.width = longestLine;
|
this.width = longestLine;
|
||||||
|
|
||||||
|
|
@ -443,14 +439,6 @@ var EditSession = function(text, mode) {
|
||||||
return this.doc.getLine(row);
|
return this.doc.getLine(row);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a line as it is displayed on screen. Tabs are replaced by spaces.
|
|
||||||
*/
|
|
||||||
this.getDisplayLine = function(row) {
|
|
||||||
var tab = new Array(this.getTabSize()+1).join(" ");
|
|
||||||
return this.doc.getLine(row).replace(/\t/g, tab);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.getLines = function(firstRow, lastRow) {
|
this.getLines = function(firstRow, lastRow) {
|
||||||
return this.doc.getLines(firstRow, lastRow);
|
return this.doc.getLines(firstRow, lastRow);
|
||||||
};
|
};
|
||||||
|
|
@ -591,11 +579,11 @@ var EditSession = function(text, mode) {
|
||||||
deltas = deltas.map(function(delta) {
|
deltas = deltas.map(function(delta) {
|
||||||
var d = {
|
var d = {
|
||||||
range: delta.range
|
range: delta.range
|
||||||
}
|
};
|
||||||
if (delta.action == "insertText" || delta.action == "insertLines")
|
if (delta.action == "insertText" || delta.action == "insertLines")
|
||||||
d.action = "removeText"
|
d.action = "removeText";
|
||||||
else
|
else
|
||||||
d.action = "insertText"
|
d.action = "insertText";
|
||||||
return d;
|
return d;
|
||||||
}).reverse();
|
}).reverse();
|
||||||
|
|
||||||
|
|
@ -612,7 +600,7 @@ var EditSession = function(text, mode) {
|
||||||
isInsert: isInsert,
|
isInsert: isInsert,
|
||||||
start: isInsert ? delta.range.start : delta.range.end,
|
start: isInsert ? delta.range.start : delta.range.end,
|
||||||
end: isInsert ? delta.range.end : delta.range.start
|
end: isInsert ? delta.range.end : delta.range.start
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (isInsert)
|
if (isInsert)
|
||||||
|
|
@ -899,9 +887,9 @@ var EditSession = function(text, mode) {
|
||||||
// and multipleWidth characters.
|
// and multipleWidth characters.
|
||||||
var len = displayed.length;
|
var len = displayed.length;
|
||||||
displayed.join("").
|
displayed.join("").
|
||||||
// Get all the tabs.
|
// Get all the tabs spaces.
|
||||||
replace(/4/g, function(m) {
|
replace(/5/g, function(m) {
|
||||||
len -= tabSize - 1;
|
len -= 1;
|
||||||
}).
|
}).
|
||||||
// Get all the multipleWidth characters.
|
// Get all the multipleWidth characters.
|
||||||
replace(/2/g, function(m) {
|
replace(/2/g, function(m) {
|
||||||
|
|
@ -943,16 +931,17 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return splits;
|
return splits;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.$getDisplayTokens = function(str) {
|
this.$getDisplayTokens = function(str) {
|
||||||
var arr = [];
|
var arr = [];
|
||||||
var tabSize = this.getTabSize();
|
var tabSize;
|
||||||
|
|
||||||
for (var i = 0; i < str.length; i++) {
|
for (var i = 0; i < str.length; i++) {
|
||||||
var c = str.charCodeAt(i);
|
var c = str.charCodeAt(i);
|
||||||
// Tab
|
// Tab
|
||||||
if (c == 9) {
|
if (c == 9) {
|
||||||
|
tabSize = this.getScreenTabSize(arr.length);
|
||||||
arr.push(TAB);
|
arr.push(TAB);
|
||||||
for (var n = 1; n < tabSize; n++) {
|
for (var n = 1; n < tabSize; n++) {
|
||||||
arr.push(TAB_SPACE);
|
arr.push(TAB_SPACE);
|
||||||
|
|
@ -962,21 +951,15 @@ var EditSession = function(text, mode) {
|
||||||
else if(c == 32) {
|
else if(c == 32) {
|
||||||
arr.push(SPACE);
|
arr.push(SPACE);
|
||||||
}
|
}
|
||||||
// CJK characters
|
// full width characters
|
||||||
else if (
|
else if (isFullWidth(c)) {
|
||||||
c >= 0x3040 && c <= 0x309F || // Hiragana
|
|
||||||
c >= 0x30A0 && c <= 0x30FF || // Katakana
|
|
||||||
c >= 0x4E00 && c <= 0x9FFF || // Single CJK ideographs
|
|
||||||
c >= 0xF900 && c <= 0xFAFF ||
|
|
||||||
c >= 0x3400 && c <= 0x4DBF
|
|
||||||
) {
|
|
||||||
arr.push(CHAR, CHAR_EXT);
|
arr.push(CHAR, CHAR_EXT);
|
||||||
} else {
|
} else {
|
||||||
arr.push(CHAR);
|
arr.push(CHAR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
}
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the width of the a string on the screen while assuming that
|
* Calculates the width of the a string on the screen while assuming that
|
||||||
|
|
@ -993,16 +976,10 @@ var EditSession = function(text, mode) {
|
||||||
var c = str.charCodeAt(i);
|
var c = str.charCodeAt(i);
|
||||||
// tab
|
// tab
|
||||||
if (c == 9) {
|
if (c == 9) {
|
||||||
screenColumn += tabSize;
|
screenColumn += this.getScreenTabSize(screenColumn);
|
||||||
}
|
}
|
||||||
// CJK characters
|
// full width characters
|
||||||
else if (
|
else if (isFullWidth(c)) {
|
||||||
c >= 0x3040 && c <= 0x309F || // Hiragana
|
|
||||||
c >= 0x30A0 && c <= 0x30FF || // Katakana
|
|
||||||
c >= 0x4E00 && c <= 0x9FFF || // Single CJK ideographs
|
|
||||||
c >= 0xF900 && c <= 0xFAFF ||
|
|
||||||
c >= 0x3400 && c <= 0x4DBF
|
|
||||||
) {
|
|
||||||
screenColumn += 2;
|
screenColumn += 2;
|
||||||
} else {
|
} else {
|
||||||
screenColumn += 1;
|
screenColumn += 1;
|
||||||
|
|
@ -1010,7 +987,7 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return screenColumn;
|
return screenColumn;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.getRowHeight = function(config, row) {
|
this.getRowHeight = function(config, row) {
|
||||||
var rows;
|
var rows;
|
||||||
|
|
@ -1021,7 +998,7 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows * config.lineHeight;
|
return rows * config.lineHeight;
|
||||||
}
|
};
|
||||||
|
|
||||||
this.getScreenLastRowColumn = function(screenRow, returnDocPosition) {
|
this.getScreenLastRowColumn = function(screenRow, returnDocPosition) {
|
||||||
if (!this.$useWrapMode) {
|
if (!this.$useWrapMode) {
|
||||||
|
|
@ -1055,7 +1032,7 @@ var EditSession = function(text, mode) {
|
||||||
|
|
||||||
var screenRow = this.documentToScreenRow(docRow, docColumn);
|
var screenRow = this.documentToScreenRow(docRow, docColumn);
|
||||||
return this.getScreenLastRowColumn(screenRow, true);
|
return this.getScreenLastRowColumn(screenRow, true);
|
||||||
}
|
};
|
||||||
|
|
||||||
this.getScreenFirstRowColumn = function(screenRow) {
|
this.getScreenFirstRowColumn = function(screenRow) {
|
||||||
if (!this.$useWrapMode) {
|
if (!this.$useWrapMode) {
|
||||||
|
|
@ -1106,6 +1083,13 @@ var EditSession = function(text, mode) {
|
||||||
return this.screenToDocumentPosition(screenRow, screenColumn).column;
|
return this.screenToDocumentPosition(screenRow, screenColumn).column;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the width of a tab character at screenColumn.
|
||||||
|
*/
|
||||||
|
this.getScreenTabSize = function(screenColumn) {
|
||||||
|
return this.$tabSize - screenColumn % this.$tabSize;
|
||||||
|
};
|
||||||
|
|
||||||
this.screenToDocumentPosition = function(row, column) {
|
this.screenToDocumentPosition = function(row, column) {
|
||||||
var line;
|
var line;
|
||||||
var docRow;
|
var docRow;
|
||||||
|
|
@ -1127,14 +1111,15 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (docRow >= linesCount) {
|
if (docRow >= linesCount) {
|
||||||
docRow = linesCount-1
|
docRow = linesCount-1;
|
||||||
row = wrapData[docRow].length;
|
row = wrapData[docRow].length;
|
||||||
}
|
}
|
||||||
docColumn = wrapData[docRow][row - 1] || 0;
|
docColumn = wrapData[docRow][row - 1] || 0;
|
||||||
line = this.getLine(docRow).substring(docColumn);
|
line = this.getLine(docRow).substring(docColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
var tabSize = this.getTabSize();
|
var tabSize,
|
||||||
|
screenColumn = 0;
|
||||||
for(var i = 0; i < line.length; i++) {
|
for(var i = 0; i < line.length; i++) {
|
||||||
var c = line.charCodeAt(i);
|
var c = line.charCodeAt(i);
|
||||||
|
|
||||||
|
|
@ -1142,21 +1127,17 @@ var EditSession = function(text, mode) {
|
||||||
docColumn += 1;
|
docColumn += 1;
|
||||||
// tab
|
// tab
|
||||||
if (c == 9) {
|
if (c == 9) {
|
||||||
|
tabSize = this.getScreenTabSize(screenColumn);
|
||||||
if (remaining >= tabSize) {
|
if (remaining >= tabSize) {
|
||||||
remaining -= tabSize;
|
remaining -= tabSize;
|
||||||
|
screenColumn += tabSize;
|
||||||
} else {
|
} else {
|
||||||
remaining = 0;
|
remaining = 0;
|
||||||
docColumn -= 1;
|
docColumn -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// CJK characters
|
// full width characters
|
||||||
else if (
|
else if (isFullWidth(c)) {
|
||||||
c >= 0x3040 && c <= 0x309F || // Hiragana
|
|
||||||
c >= 0x30A0 && c <= 0x30FF || // Katakana
|
|
||||||
c >= 0x4E00 && c <= 0x9FFF || // Single CJK ideographs
|
|
||||||
c >= 0xF900 && c <= 0xFAFF ||
|
|
||||||
c >= 0x3400 && c <= 0x4DBF
|
|
||||||
) {
|
|
||||||
if (remaining >= 2) {
|
if (remaining >= 2) {
|
||||||
remaining -= 2;
|
remaining -= 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1164,6 +1145,7 @@ var EditSession = function(text, mode) {
|
||||||
docColumn -= 1;
|
docColumn -= 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
screenColumn += 1;
|
||||||
remaining -= 1;
|
remaining -= 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1173,7 +1155,7 @@ var EditSession = function(text, mode) {
|
||||||
|
|
||||||
// Clamp docColumn.
|
// Clamp docColumn.
|
||||||
if (this.$useWrapMode) {
|
if (this.$useWrapMode) {
|
||||||
column = wrapData[docRow][row]
|
column = wrapData[docRow][row];
|
||||||
if (docColumn >= column) {
|
if (docColumn >= column) {
|
||||||
// We remove one character at the end such that the docColumn
|
// We remove one character at the end such that the docColumn
|
||||||
// position returned is not associated to the next row on the
|
// position returned is not associated to the next row on the
|
||||||
|
|
@ -1228,11 +1210,11 @@ var EditSession = function(text, mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return [screenRow, screenRowOffset];
|
return [screenRow, screenRowOffset];
|
||||||
}
|
};
|
||||||
|
|
||||||
this.documentToScreenRow = function(docRow, docColumn) {
|
this.documentToScreenRow = function(docRow, docColumn) {
|
||||||
return this.$documentToScreenRow(docRow, docColumn)[0];
|
return this.$documentToScreenRow(docRow, docColumn)[0];
|
||||||
}
|
};
|
||||||
|
|
||||||
this.documentToScreenPosition = function(pos, column) {
|
this.documentToScreenPosition = function(pos, column) {
|
||||||
var str;
|
var str;
|
||||||
|
|
@ -1291,6 +1273,41 @@ var EditSession = function(text, mode) {
|
||||||
screenRows += this.$wrapData[row].length + 1;
|
screenRows += this.$wrapData[row].length + 1;
|
||||||
}
|
}
|
||||||
return screenRows;
|
return screenRows;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isFullWidth(c) {
|
||||||
|
return c >= 0x1100 && c <= 0x115F ||
|
||||||
|
c >= 0x11A3 && c <= 0x11A7 ||
|
||||||
|
c >= 0x11FA && c <= 0x11FF ||
|
||||||
|
c >= 0x2329 && c <= 0x232A ||
|
||||||
|
c >= 0x2E80 && c <= 0x2E99 ||
|
||||||
|
c >= 0x2E9B && c <= 0x2EF3 ||
|
||||||
|
c >= 0x2F00 && c <= 0x2FD5 ||
|
||||||
|
c >= 0x2FF0 && c <= 0x2FFB ||
|
||||||
|
c >= 0x3000 && c <= 0x303E ||
|
||||||
|
c >= 0x3041 && c <= 0x3096 ||
|
||||||
|
c >= 0x3099 && c <= 0x30FF ||
|
||||||
|
c >= 0x3105 && c <= 0x312D ||
|
||||||
|
c >= 0x3131 && c <= 0x318E ||
|
||||||
|
c >= 0x3190 && c <= 0x31BA ||
|
||||||
|
c >= 0x31C0 && c <= 0x31E3 ||
|
||||||
|
c >= 0x31F0 && c <= 0x321E ||
|
||||||
|
c >= 0x3220 && c <= 0x3247 ||
|
||||||
|
c >= 0x3250 && c <= 0x32FE ||
|
||||||
|
c >= 0x3300 && c <= 0x4DBF ||
|
||||||
|
c >= 0x4E00 && c <= 0xA48C ||
|
||||||
|
c >= 0xA490 && c <= 0xA4C6 ||
|
||||||
|
c >= 0xA960 && c <= 0xA97C ||
|
||||||
|
c >= 0xAC00 && c <= 0xD7A3 ||
|
||||||
|
c >= 0xD7B0 && c <= 0xD7C6 ||
|
||||||
|
c >= 0xD7CB && c <= 0xD7FB ||
|
||||||
|
c >= 0xF900 && c <= 0xFAFF ||
|
||||||
|
c >= 0xFE10 && c <= 0xFE19 ||
|
||||||
|
c >= 0xFE30 && c <= 0xFE52 ||
|
||||||
|
c >= 0xFE54 && c <= 0xFE66 ||
|
||||||
|
c >= 0xFE68 && c <= 0xFE6B ||
|
||||||
|
c >= 0xFF01 && c <= 0xFF60 ||
|
||||||
|
c >= 0xFFE0 && c <= 0xFFE6;
|
||||||
}
|
}
|
||||||
|
|
||||||
}).call(EditSession.prototype);
|
}).call(EditSession.prototype);
|
||||||
|
|
|
||||||
|
|
@ -160,18 +160,21 @@ var Text = function(parentEl) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.$tabStrings = [];
|
||||||
this.$computeTabString = function() {
|
this.$computeTabString = function() {
|
||||||
var tabSize = this.session.getTabSize();
|
var tabSize = this.session.getTabSize();
|
||||||
|
var tabStr = this.$tabStrings = [0];
|
||||||
|
for (var i = 1; i < tabSize + 1; i++) {
|
||||||
if (this.showInvisibles) {
|
if (this.showInvisibles) {
|
||||||
var halfTab = (tabSize) / 2;
|
tabStr.push("<span class='ace_invisible'>"
|
||||||
this.$tabString = "<span class='ace_invisible'>"
|
|
||||||
+ new Array(Math.floor(halfTab)).join(" ")
|
|
||||||
+ this.TAB_CHAR
|
+ this.TAB_CHAR
|
||||||
+ new Array(Math.ceil(halfTab)+1).join(" ")
|
+ new Array(i).join(" ")
|
||||||
+ "</span>";
|
+ "</span>");
|
||||||
} else {
|
} else {
|
||||||
this.$tabString = new Array(tabSize+1).join(" ");
|
tabStr.push(new Array(i+1).join(" "));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateLines = function(config, firstRow, lastRow) {
|
this.updateLines = function(config, firstRow, lastRow) {
|
||||||
|
|
@ -277,35 +280,37 @@ var Text = function(parentEl) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.$renderLine = function(stringBuilder, row, tokens) {
|
this.$renderLine = function(stringBuilder, row, tokens) {
|
||||||
if (this.showInvisibles) {
|
var _self = this,
|
||||||
var self = this;
|
characterWidth = this.config.characterWidth,
|
||||||
var spaceRe = /( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])/g;
|
screenColumn = 0;
|
||||||
var spaceReplace = function(space) {
|
|
||||||
if (space.charCodeAt(0) == 32)
|
|
||||||
return new Array(space.length+1).join(" ");
|
|
||||||
else {
|
|
||||||
var space = new Array(space.length+1).join(self.SPACE_CHAR);
|
|
||||||
return "<span class='ace_invisible'>" + space + "</span>";
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var spaceRe = /[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/g;
|
|
||||||
var spaceReplace = " ";
|
|
||||||
}
|
|
||||||
|
|
||||||
var _self = this;
|
|
||||||
var characterWidth = this.config.characterWidth;
|
|
||||||
function addToken(token, value) {
|
function addToken(token, value) {
|
||||||
var output = value
|
var output = value
|
||||||
.replace(/&/g, "&")
|
.replace(/\t|&|<|( +)|([\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000])|[\u1100-\u115F]|[\u11A3-\u11A7]|[\u11FA-\u11FF]|[\u2329-\u232A]|[\u2E80-\u2E99]|[\u2E9B-\u2EF3]|[\u2F00-\u2FD5]|[\u2FF0-\u2FFB]|[\u3000-\u303E]|[\u3041-\u3096]|[\u3099-\u30FF]|[\u3105-\u312D]|[\u3131-\u318E]|[\u3190-\u31BA]|[\u31C0-\u31E3]|[\u31F0-\u321E]|[\u3220-\u3247]|[\u3250-\u32FE]|[\u3300-\u4DBF]|[\u4E00-\uA48C]|[\uA490-\uA4C6]|[\uA960-\uA97C]|[\uAC00-\uD7A3]|[\uD7B0-\uD7C6]|[\uD7CB-\uD7FB]|[\uF900-\uFAFF]|[\uFE10-\uFE19]|[\uFE30-\uFE52]|[\uFE54-\uFE66]|[\uFE68-\uFE6B]|[\uFF01-\uFF60]|[\uFFE0-\uFFE6]/g, function(c, a, b, tabIdx, idx4) {
|
||||||
.replace(/</g, "<")
|
if (c.charCodeAt(0) == 32) {
|
||||||
.replace(spaceRe, spaceReplace)
|
return new Array(c.length+1).join(" ");
|
||||||
.replace(/\t/g, _self.$tabString)
|
} else if (c == "\t") {
|
||||||
.replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) {
|
var tabSize = _self.session.
|
||||||
|
getScreenTabSize(screenColumn + tabIdx);
|
||||||
|
screenColumn += tabSize - 1;
|
||||||
|
return _self.$tabStrings[tabSize];
|
||||||
|
} else if (c == "&") {
|
||||||
|
return "&";
|
||||||
|
} else if (c == "<") {
|
||||||
|
return "<";
|
||||||
|
} else if (c.match(/[\v\f \u00a0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000]/)) {
|
||||||
|
if (this.showInvisibles) {
|
||||||
|
var space = new Array(c.length+1).join(self.SPACE_CHAR);
|
||||||
|
return "<span class='ace_invisible'>" + space + "</span>";
|
||||||
|
} else {
|
||||||
|
return " "
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
screenColumn += 1;
|
||||||
return "<span class='ace_cjk' style='width:" + (characterWidth * 2) + "px'>" + c + "</span>"
|
return "<span class='ace_cjk' style='width:" + (characterWidth * 2) + "px'>" + c + "</span>"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
screenColumn += value.length;
|
||||||
|
|
||||||
if (!_self.$textToken[token.type]) {
|
if (!_self.$textToken[token.type]) {
|
||||||
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
var classes = "ace_" + token.type.replace(/\./g, " ace_");
|
||||||
|
|
@ -344,7 +349,9 @@ var Text = function(parentEl) {
|
||||||
"<div style='height:",
|
"<div style='height:",
|
||||||
this.config.lineHeight, "px",
|
this.config.lineHeight, "px",
|
||||||
"'>");
|
"'>");
|
||||||
|
|
||||||
split ++;
|
split ++;
|
||||||
|
screenColumn = 0;
|
||||||
splitChars = splits[split] || Number.MAX_VALUE;
|
splitChars = splits[split] || Number.MAX_VALUE;
|
||||||
}
|
}
|
||||||
if (value.length != 0) {
|
if (value.length != 0) {
|
||||||
|
|
|
||||||
|
|
@ -45,24 +45,52 @@ var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightR
|
||||||
var RubyHighlightRules = function() {
|
var RubyHighlightRules = function() {
|
||||||
|
|
||||||
var builtinFunctions = lang.arrayToMap(
|
var builtinFunctions = lang.arrayToMap(
|
||||||
("abort|Array|at_exit|autoload|binding|block_given?|callcc|caller|catch|chomp|chomp!|chop|chop!|eval|exec|exit|exit!" +
|
("abort|Array|assert|assert_equal|assert_not_equal|assert_same|assert_not_same|" +
|
||||||
"fail|Float|fork|format|gets|global_variables|gsub|gsub!|Integer|lambda|load|local_variables|loop|open|p|print|" +
|
"assert_nil|assert_not_nil|assert_match|assert_no_match|assert_in_delta|assert_throws|" +
|
||||||
"printf|proc|putc|puts|raise|rand|readline|readlines|require|scan|select|set_trace_func|sleep|split|sprintf|srand|" +
|
"assert_raise|assert_nothing_raised|assert_instance_of|assert_kind_of|assert_respond_to|" +
|
||||||
"String|syscall|system|sub|sub!|test|throw|trace_var|trap|untrace_var|" +
|
"assert_operator|assert_send|assert_difference|assert_no_difference|assert_recognizes|" +
|
||||||
"atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan").split("|")
|
"assert_generates|assert_response|assert_redirected_to|assert_template|assert_select|" +
|
||||||
|
"assert_select_email|assert_select_rjs|assert_select_encoded|css_select|at_exit|" +
|
||||||
|
"attr|attr_writer|attr_reader|attr_accessor|attr_accessible|autoload|binding|block_given?|callcc|" +
|
||||||
|
"caller|catch|chomp|chomp!|chop|chop!|defined?|delete_via_redirect|eval|exec|exit|" +
|
||||||
|
"exit!|fail|Float|flunk|follow_redirect!|fork|form_for|form_tag|format|gets|global_variables|gsub|" +
|
||||||
|
"gsub!|get_via_redirect|h|host!|https?|https!|include|Integer|lambda|link_to|" +
|
||||||
|
"link_to_unless_current|link_to_function|link_to_remote|load|local_variables|loop|open|open_session|" +
|
||||||
|
"p|print|printf|proc|putc|puts|post_via_redirect|put_via_redirect|raise|rand|" +
|
||||||
|
"raw|readline|readlines|redirect?|request_via_redirect|require|scan|select|" +
|
||||||
|
"set_trace_func|sleep|split|sprintf|srand|String|stylesheet_link_tag|syscall|system|sub|sub!|test|" +
|
||||||
|
"throw|trace_var|trap|untrace_var|atan2|cos|exp|frexp|ldexp|log|log10|sin|sqrt|tan|" +
|
||||||
|
"render|javascript_include_tag|csrf_meta_tag|label_tag|text_field_tag|submit_tag|check_box_tag|" +
|
||||||
|
"content_tag|radio_button_tag|text_area_tag|password_field_tag|hidden_field_tag|" +
|
||||||
|
"fields_for|select_tag|options_for_select|options_from_collection_for_select|collection_select|" +
|
||||||
|
"time_zone_select|select_date|select_time|select_datetime|date_select|time_select|datetime_select|" +
|
||||||
|
"select_year|select_month|select_day|select_hour|select_minute|select_second|file_field_tag|" +
|
||||||
|
"file_field|respond_to|skip_before_filter|around_filter|after_filter|verify|" +
|
||||||
|
"protect_from_forgery|rescue_from|helper_method|redirect_to|before_filter|" +
|
||||||
|
"send_data|send_file|validates_presence_of|validates_uniqueness_of|validates_length_of|" +
|
||||||
|
"validates_format_of|validates_acceptance_of|validates_associated|validates_exclusion_of|" +
|
||||||
|
"validates_inclusion_of|validates_numericality_of|validates_with|validates_each|" +
|
||||||
|
"authenticate_or_request_with_http_basic|authenticate_or_request_with_http_digest|" +
|
||||||
|
"filter_parameter_logging|match|get|post|resources|redirect|scope|assert_routing|" +
|
||||||
|
"translate|localize|extract_locale_from_tld|t|l|caches_page|expire_page|caches_action|expire_action|" +
|
||||||
|
"cache|expire_fragment|expire_cache_for|observe|cache_sweeper|" +
|
||||||
|
"has_many|has_one|belongs_to|has_and_belongs_to_many").split("|")
|
||||||
);
|
);
|
||||||
|
|
||||||
var keywords = lang.arrayToMap(
|
var keywords = lang.arrayToMap(
|
||||||
("alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|__FILE__|finally|for|" +
|
("alias|and|BEGIN|begin|break|case|class|def|defined|do|else|elsif|END|end|ensure|" +
|
||||||
"if|in|__LINE__|module|next|not|or|redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield").split("|")
|
"__FILE__|finally|for|gem|if|in|__LINE__|module|next|not|or|private|protected|public|" +
|
||||||
|
"redo|rescue|retry|return|super|then|undef|unless|until|when|while|yield").split("|")
|
||||||
);
|
);
|
||||||
|
|
||||||
var buildinConstants = lang.arrayToMap(
|
var buildinConstants = lang.arrayToMap(
|
||||||
("true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING").split("|")
|
("true|TRUE|false|FALSE|nil|NIL|ARGF|ARGV|DATA|ENV|RUBY_PLATFORM|RUBY_RELEASE_DATE|" +
|
||||||
|
"RUBY_VERSION|STDERR|STDIN|STDOUT|TOPLEVEL_BINDING").split("|")
|
||||||
);
|
);
|
||||||
|
|
||||||
var builtinVariables = lang.arrayToMap(
|
var builtinVariables = lang.arrayToMap(
|
||||||
("\$DEBUG|\$defout|\$FILENAME|\$LOAD_PATH|\$SAFE|\$stdin|\$stdout|\$stderr|\$VERBOSE").split("|")
|
("\$DEBUG|\$defout|\$FILENAME|\$LOAD_PATH|\$SAFE|\$stdin|\$stdout|\$stderr|\$VERBOSE|" +
|
||||||
|
"$!|root_url|flash|session|cookies|params|request|response|logger").split("|")
|
||||||
);
|
);
|
||||||
|
|
||||||
// regexp must not have capturing parentheses. Use (?:) instead.
|
// regexp must not have capturing parentheses. Use (?:) instead.
|
||||||
|
|
@ -86,6 +114,18 @@ var RubyHighlightRules = function() {
|
||||||
}, {
|
}, {
|
||||||
token : "string", // single line
|
token : "string", // single line
|
||||||
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"
|
||||||
|
}, {
|
||||||
|
token : "string", // backtick string
|
||||||
|
regex : "[`](?:(?:\\\\.)|(?:[^'\\\\]))*?[`]"
|
||||||
|
}, {
|
||||||
|
token : "variable.instancce", // instance variable
|
||||||
|
regex : "@{1,2}(?:[a-zA-Z_]|\d)+"
|
||||||
|
}, {
|
||||||
|
token : "variable.class", // class name
|
||||||
|
regex : "[A-Z](?:[a-zA-Z_]|\d)+"
|
||||||
|
}, {
|
||||||
|
token : "string", // symbol
|
||||||
|
regex : "[:](?:[a-zA-Z]|\d)+"
|
||||||
}, {
|
}, {
|
||||||
token : "constant.numeric", // hex
|
token : "constant.numeric", // hex
|
||||||
regex : "0[xX][0-9a-fA-F]+\\b"
|
regex : "0[xX][0-9a-fA-F]+\\b"
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,6 @@ var Selection = function(session) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorBy = function(rows, chars) {
|
this.moveCursorBy = function(rows, chars) {
|
||||||
if (this.session.getUseWrapMode()) {
|
|
||||||
var screenPos = this.session.documentToScreenPosition(
|
var screenPos = this.session.documentToScreenPosition(
|
||||||
this.selectionLead.row,
|
this.selectionLead.row,
|
||||||
this.selectionLead.column
|
this.selectionLead.column
|
||||||
|
|
@ -391,10 +390,6 @@ var Selection = function(session) {
|
||||||
var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
|
var docPos = this.session.screenToDocumentPosition(screenPos.row + rows, screenCol);
|
||||||
|
|
||||||
this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0);
|
this.moveCursorTo(docPos.row, docPos.column + chars, chars == 0);
|
||||||
} else {
|
|
||||||
var docColumn = (chars == 0 && this.$desiredColumn) || this.selectionLead.column;
|
|
||||||
this.moveCursorTo(this.selectionLead.row + rows, docColumn + chars, chars == 0);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorToPosition = function(position) {
|
this.moveCursorToPosition = function(position) {
|
||||||
|
|
@ -408,11 +403,9 @@ var Selection = function(session) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.moveCursorToScreen = function(row, column, preventUpdateDesiredColumn) {
|
this.moveCursorToScreen = function(row, column, preventUpdateDesiredColumn) {
|
||||||
if (this.session.getUseWrapMode()) {
|
|
||||||
var pos = this.session.screenToDocumentPosition(row, column);
|
var pos = this.session.screenToDocumentPosition(row, column);
|
||||||
row = pos.row;
|
row = pos.row;
|
||||||
column = pos.column;
|
column = pos.column;
|
||||||
}
|
|
||||||
this.moveCursorTo(row, column, preventUpdateDesiredColumn);
|
this.moveCursorTo(row, column, preventUpdateDesiredColumn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,18 +140,19 @@ var Test = {
|
||||||
assert.equal(session.documentToScreenColumn(0, 0), 0);
|
assert.equal(session.documentToScreenColumn(0, 0), 0);
|
||||||
assert.equal(session.documentToScreenColumn(0, 4), 4);
|
assert.equal(session.documentToScreenColumn(0, 4), 4);
|
||||||
assert.equal(session.documentToScreenColumn(0, 5), 5);
|
assert.equal(session.documentToScreenColumn(0, 5), 5);
|
||||||
assert.equal(session.documentToScreenColumn(0, 6), 9);
|
assert.equal(session.documentToScreenColumn(0, 6), 8);
|
||||||
assert.equal(session.documentToScreenColumn(0, 12), 15);
|
assert.equal(session.documentToScreenColumn(0, 12), 14);
|
||||||
assert.equal(session.documentToScreenColumn(0, 13), 19);
|
assert.equal(session.documentToScreenColumn(0, 13), 16);
|
||||||
|
|
||||||
session.setTabSize(2);
|
session.setTabSize(2);
|
||||||
|
|
||||||
assert.equal(session.documentToScreenColumn(0, 0), 0);
|
assert.equal(session.documentToScreenColumn(0, 0), 0);
|
||||||
assert.equal(session.documentToScreenColumn(0, 4), 4);
|
assert.equal(session.documentToScreenColumn(0, 4), 4);
|
||||||
assert.equal(session.documentToScreenColumn(0, 5), 5);
|
assert.equal(session.documentToScreenColumn(0, 5), 5);
|
||||||
assert.equal(session.documentToScreenColumn(0, 6), 7);
|
assert.equal(session.documentToScreenColumn(0, 6), 6);
|
||||||
assert.equal(session.documentToScreenColumn(0, 12), 13);
|
assert.equal(session.documentToScreenColumn(0, 7), 7);
|
||||||
assert.equal(session.documentToScreenColumn(0, 13), 15);
|
assert.equal(session.documentToScreenColumn(0, 12), 12);
|
||||||
|
assert.equal(session.documentToScreenColumn(0, 13), 14);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: convert document to screen coordinates with leading tabs": function() {
|
"test: convert document to screen coordinates with leading tabs": function() {
|
||||||
|
|
@ -194,10 +195,20 @@ var Test = {
|
||||||
assert.equal(session.screenToDocumentColumn(0, 5), 5);
|
assert.equal(session.screenToDocumentColumn(0, 5), 5);
|
||||||
assert.equal(session.screenToDocumentColumn(0, 6), 5);
|
assert.equal(session.screenToDocumentColumn(0, 6), 5);
|
||||||
assert.equal(session.screenToDocumentColumn(0, 7), 5);
|
assert.equal(session.screenToDocumentColumn(0, 7), 5);
|
||||||
assert.equal(session.screenToDocumentColumn(0, 8), 5);
|
assert.equal(session.screenToDocumentColumn(0, 8), 6);
|
||||||
assert.equal(session.screenToDocumentColumn(0, 9), 6);
|
assert.equal(session.screenToDocumentColumn(0, 9), 7);
|
||||||
assert.equal(session.screenToDocumentColumn(0, 15), 12);
|
assert.equal(session.screenToDocumentColumn(0, 15), 12);
|
||||||
assert.equal(session.screenToDocumentColumn(0, 19), 13);
|
assert.equal(session.screenToDocumentColumn(0, 19), 16);
|
||||||
|
|
||||||
|
session.setTabSize(2);
|
||||||
|
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 0), 0);
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 4), 4);
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 5), 5);
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 6), 6);
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 12), 12);
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 13), 12);
|
||||||
|
assert.equal(session.screenToDocumentColumn(0, 14), 13);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test: screenToDocument with soft wrap and multi byte characters": function() {
|
"test: screenToDocument with soft wrap and multi byte characters": function() {
|
||||||
|
|
@ -227,13 +238,12 @@ var Test = {
|
||||||
|
|
||||||
"test: wrapLine split function" : function() {
|
"test: wrapLine split function" : function() {
|
||||||
var splits;
|
var splits;
|
||||||
var computeWrapSplits = EditSession.prototype.$computeWrapSplits;
|
|
||||||
var c = 0;
|
var c = 0;
|
||||||
|
|
||||||
function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {
|
function computeAndAssert(line, assertEqual, wrapLimit, tabSize) {
|
||||||
wrapLimit = wrapLimit || 12;
|
wrapLimit = wrapLimit || 12;
|
||||||
tabSize = tabSize || 4;
|
tabSize = tabSize || 4;
|
||||||
splits = computeWrapSplits.call(EditSession.prototype, line, wrapLimit, tabSize);
|
var splits = EditSession.prototype.$computeWrapSplits(line, wrapLimit, tabSize);
|
||||||
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
// console.log("String:", line, "Result:", splits, "Expected:", assertEqual);
|
||||||
assert.ok(splits.length == assertEqual.length);
|
assert.ok(splits.length == assertEqual.length);
|
||||||
for (var i = 0; i < splits.length; i++) {
|
for (var i = 0; i < splits.length; i++) {
|
||||||
|
|
@ -297,7 +307,7 @@ var Test = {
|
||||||
|
|
||||||
assert.equal(session.$getDisplayTokens("\t").length, 4);
|
assert.equal(session.$getDisplayTokens("\t").length, 4);
|
||||||
assert.equal(session.$getDisplayTokens("abc").length, 3);
|
assert.equal(session.$getDisplayTokens("abc").length, 3);
|
||||||
assert.equal(session.$getDisplayTokens("abc\t").length, 7);
|
assert.equal(session.$getDisplayTokens("abc\t").length, 4);
|
||||||
},
|
},
|
||||||
|
|
||||||
"test issue 83": function() {
|
"test issue 83": function() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue