First iteration of implementing real real tabs

This commit is contained in:
Julian Viereck 2011-03-18 23:30:25 +01:00
commit 1a5a071c7d
2 changed files with 62 additions and 20 deletions

View file

@ -944,13 +944,14 @@ var EditSession = function(text, mode) {
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) {
arr.push(TAB); arr.push(TAB);
tabSize = this.getScreenTabSize(arr.length);
for (var n = 1; n < tabSize; n++) { for (var n = 1; n < tabSize; n++) {
arr.push(TAB_SPACE); arr.push(TAB_SPACE);
} }
@ -990,7 +991,7 @@ 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 // CJK characters
else if ( else if (
@ -1103,6 +1104,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;
@ -1131,7 +1139,8 @@ var EditSession = function(text, mode) {
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);
@ -1139,8 +1148,10 @@ 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;
@ -1154,6 +1165,7 @@ var EditSession = function(text, mode) {
c >= 0xF900 && c <= 0xFAFF || c >= 0xF900 && c <= 0xFAFF ||
c >= 0x3400 && c <= 0x4DBF c >= 0x3400 && c <= 0x4DBF
) { ) {
screenColumn += 2;
if (remaining >= 2) { if (remaining >= 2) {
remaining -= 2; remaining -= 2;
} else { } else {
@ -1161,6 +1173,7 @@ var EditSession = function(text, mode) {
docColumn -= 1; docColumn -= 1;
} }
} else { } else {
screenColumn += 2;
remaining -= 1; remaining -= 1;
} }
} else { } else {

View file

@ -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();
if (this.showInvisibles) { var tabStr = this.$tabStrings = [0];
var halfTab = (tabSize) / 2; for (var i = 1; i < tabSize + 1; i++) {
this.$tabString = "<span class='ace_invisible'>" if (this.showInvisibles) {
+ new Array(Math.floor(halfTab)).join("&#160;") tabStr.push("<span class='ace_invisible'>"
+ this.TAB_CHAR + this.TAB_CHAR
+ new Array(Math.ceil(halfTab)+1).join("&#160;") + new Array(i).join("&#160;")
+ "</span>"; + "</span>");
} else { } else {
this.$tabString = new Array(tabSize+1).join("&#160;"); tabStr.push(new Array(i+1).join("&#160;"));
}
} }
}; };
this.updateLines = function(config, firstRow, lastRow) { this.updateLines = function(config, firstRow, lastRow) {
@ -295,17 +298,41 @@ var Text = function(parentEl) {
var spaceReplace = "&#160;"; var spaceReplace = "&#160;";
} }
var _self = this; var _self = this,
var characterWidth = this.config.characterWidth; characterWidth = this.config.characterWidth,
screenColumn = 0;
function addToken(token, value) { function addToken(token, value) {
var output = value var output = value
.replace(/&/g, "&amp;") .replace(/\t|&|<|[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c, idx) {
.replace(/</g, "&lt;") if (c == "\t") {
var tabSize = _self.session.
getScreenTabSize(screenColumn + idx);
screenColumn += tabSize - 1;
return _self.$tabStrings[tabSize];
} else if (c == "&") {
return "&amp";
} else if (c == "<") {
return "&lt;";
} else {
screenColumn += 1;
return "<span class='ace_cjk' style='width:" + (characterWidth * 2) + "px'>" + c + "</span>"
}
})
// .replace(/\t/g, function(c, idx) {
// idx += screenColumnOld;
// var tabSize = _self.session.getScreenTabSize(idx);
// screenColumn += tabSize - 1;
// return _self.$tabStrings[tabSize];
// })
// .replace(/&/g, "&amp;")
// .replace(/</g, "&lt;")
.replace(spaceRe, spaceReplace) .replace(spaceRe, spaceReplace)
.replace(/\t/g, _self.$tabString) // .replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) {
.replace(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]/g, function(c) { // 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 +371,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) {