penguin/AstroJS

Javascript framework for my blog

commit 50686073d8c055a0fea8bad2e5bfaf4caa7580b9

author斟酌 鵬兄 <tgckpg@gmail.com>
date2017-01-09T02:18:21Z
subjectReplaced quirky tab char with virtual space chars
commit 50686073d8c055a0fea8bad2e5bfaf4caa7580b9
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2017-01-09T02:18:21Z

    Replaced quirky tab char with virtual space chars
---
 botanjs/src/Components/Vim/Cursor.js         | 92 ++++++++++++++++++++--------
 botanjs/src/Components/Vim/LineBuffer.js     | 13 ++--
 botanjs/src/Components/Vim/LineFeeder.js     | 16 +++--
 botanjs/src/externs/Components.Vim.Cursor.js |  2 +
 4 files changed, 87 insertions(+), 36 deletions(-)

diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index f8d2dd9..810bf70 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -9,6 +9,8 @@
 
 	var Actions = __import( "Components.Vim.Actions.*" );
 
+	var occurence = __import( "System.utils.Perf.CountSubstr" );
+
 	var LineOffset = function( buffs, l )
 	{
 		/** @type {Components.Vim.LineBuffer} */
@@ -69,6 +71,8 @@
 		this.cols = feeder.firstBuffer.cols;
 
 		// The preferred X position
+		// i.e. last line was at pos 23
+		// moving to next line will prefer pos at 23
 		this.pX = 0;
 
 		// The displaying X position
@@ -129,10 +133,11 @@
 		var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart;
 
 		jumpX += Math.ceil( jumpX / pline.cols ) - 1;
+		jumpX += occurence( content.substring( lineStart + 1, aPos ), "\t" ) * ( pline.tabWidth - 1 );
 
 		if( jumpY ) this.moveY( jumpY );
 
-		// This needed because first line does not contain first "\n" character
+		// This is needed because first line does not contain the first "\n" character
 		if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --;
 
 		this.moveX( - Number.MAX_VALUE );
@@ -179,26 +184,14 @@
 		var hasPhantomSpace = true;
 
 		// Empty lines has length of 1
-		// If length larger than a, need to compensate the lineEnd
-		// for phantomSpace
+		// Need to compensate the lineEnd for phantomSpace
+		// if length is 1 < and != line.cols
 		if( 1 < cLen )
 		{
-			// Begin check if whether this line contains phantomSpace
-			var lineNum = line.lineNum - 1;
-			var str = feeder.content;
-			for( var i = str.indexOf( "\n" ), j = 0; 0 <= i; i = str.indexOf( "\n", i ), j ++ )
-			{
-				if( lineNum == j ) break;
-				i ++;
-			}
-
-			if( j == 0 && i == -1 ) i = 0;
-
-			var end = str.indexOf( "\n", i + 1 );
-			end = end == -1 ? str.length : end;
-
-			// Actual LineLength
-			var hasPhantomSpace = 0 < ( end - i - 1 ) % line.cols;
+			// Begin check if this line contains phantomSpace
+			// hasPhantomSpace = 0 < ( rawLine.displayLength ) % cols
+			var rline = this.rawLine;
+			hasPhantomSpace = 0 < ( rline.length + occurence( rline, "\t" ) * ( line.tabWidth - 1 ) ) % line.cols;
 
 			if( hasPhantomSpace )
 			{
@@ -421,14 +414,12 @@
 	Cursor.prototype.suppressEvent = function() { ++ this.__suppEvt; };
 	Cursor.prototype.unsuppressEvent = function() { -- this.__suppEvt; };
 
-	Cursor.prototype.getLine = function()
+	Cursor.prototype.getLine = function( raw )
 	{
 		var feeder = this.feeder;
 		var line = feeder.firstBuffer;
 		var eBuffer = feeder.lastBuffer.next;
-		for( var i = 0;
-			line != eBuffer;
-			line = line.next )
+		for( var i = 0; line != eBuffer; line = line.next )
 		{
 			if( line.br ) i ++;
 			if( this.Y == i ) return line;
@@ -437,26 +428,49 @@
 		return null;
 	};
 
+	__readOnly( Cursor.prototype, "rawLine", function()
+	{
+		var str = this.feeder.content;
+		var lineNum = this.getLine().lineNum - 1;
+		var i = str.indexOf( "\n" ), j = 0;
+
+		for( ; 0 <= i; i = str.indexOf( "\n", i ), j ++ )
+		{
+			if( lineNum == j ) break;
+			i ++;
+		}
+
+		if( j == 0 && i == -1 ) i = 0;
+
+		var end = str.indexOf( "\n", i + 1 );
+		return str.substring( i + 1, end );
+	} );
+
 	// The position offset relative to current line
 	__readOnly( Cursor.prototype, "aX", function()
 	{
 		var X = this.X;
 		var f = this.feeder;
 
-		var w = 1;
+		var w = 0;
 
 		// Calculate wordwrap offset
 		if( f.wrap )
 		{
 			var lines = this.getLine().visualLines;
 
+			// Since w represent valid absX position
+			// w couldn't handle INSERT at the line end with phantomSpace
+			// because phantomSpace is not a valid character
+			// So we calculate along with the phantomSpace here
+			var phantomSpace = X;
 			for( var i in lines )
 			{
 				/** @type {Components.Vim.LineBuffer} */
 				var vline = lines[ i ];
 
 				// Actual length
-				var aLen = vline.content.toString().length;
+				var aLen = vline.content.length;
 
 				// Visual length
 				var vLen = vline.toString().length;
@@ -467,10 +481,36 @@
 				if( 0 <= X )
 				{
 					w += aLen;
+					phantomSpace -= 1 + occurence( vline.content, "\t" ) * ( vline.tabWidth - 1 );
 				}
 				else if( X < 0 )
 				{
-					w += X + vLen;
+					X += vLen + 1;
+
+					var rline = this.rawLine.substr( w );
+					var l = rline.length;
+
+					var j = 0;
+
+					if( rline[ 0 ] == "\t" )
+					{
+						X -= vline.tabWidth - 1;
+						phantomSpace -= vline.tabWidth - 1;
+					}
+
+					for( var i = 1; j < X && i < rline.length; i ++ )
+					{
+						if( rline[ i ] == "\t" )
+						{
+							X -= vline.tabWidth - 1;
+							phantomSpace -= vline.tabWidth - 1;
+						}
+						j ++;
+					}
+
+					w += j;
+
+					if( w < phantomSpace ) w = phantomSpace;
 					break;
 				}
 			}
diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js
index e097f83..88601fb 100644
--- a/botanjs/src/Components/Vim/LineBuffer.js
+++ b/botanjs/src/Components/Vim/LineBuffer.js
@@ -13,7 +13,9 @@
 		this.br = false;
 		this.placeholder = true;
 		this.lineNum = 0;
-		this.tabWidth = 8;
+		this.tabWidth = 4;
+		this.__tabc = "";
+		for( var i = 0; i < this.tabWidth; i ++ ) this.__tabc += " ";
 
 		if( nextLineBuffer )
 		{
@@ -105,13 +107,14 @@
 
 	LineBuffer.prototype.toString = function()
 	{
-		var c = this.cols - occurence( this.content, "\t" ) * ( this.tabWidth - 1 );
-		if( this.content.length < c )
+		var cont = this.content.replace( /\t/g, this.__tabc );
+
+		if( cont.length < this.cols )
 		{
-			return this.content + " ";
+			return cont + " ";
 		}
 
-		return this.content || " ";
+		return cont || " ";
 	};
 
 	__readOnly( LineBuffer.prototype, "nextLine", function()
diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
index 95b5ab4..4098773 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -158,9 +158,7 @@
 			}
 		}
 
-		this.firstBuffer.Push(
-			this.content.substr( f + 1 )
-			, this.wrap, i );
+		this.firstBuffer.Push( this.content.substr( f + 1 ), this.wrap, i );
 
 		this.panX = X;
 		this.panY = Y;
@@ -213,11 +211,19 @@
 		var line = this.cursor.getLine();
 		var tabStat = "";
 
-		var tabs = line.content.match( /\t/g );
+		var tabs = 0;
+		var l = this.cursor.aPos;
+		var i = l - X;
+		do
+		{
+			if( this.content[ i + 1 ] == "\t" ) tabs ++;
+			i ++;
+		}
+		while( i < l )
 
 		if( tabs )
 		{
-			tabStat = "-" + ( X + tabs.length * ( line.tabWidth - 1 ) );
+			tabStat = "-" + ( X + tabs * ( line.tabWidth - 1 ) );
 		}
 
 		return ( line.lineNum + 1 ) + "," + X + tabStat;
diff --git a/botanjs/src/externs/Components.Vim.Cursor.js b/botanjs/src/externs/Components.Vim.Cursor.js
index 8cf84f8..5bdc8b1 100644
--- a/botanjs/src/externs/Components.Vim.Cursor.js
+++ b/botanjs/src/externs/Components.Vim.Cursor.js
@@ -63,3 +63,5 @@ Components.Vim.Cursor.position;
 Components.Vim.Cursor.position.start;
 /** @type Number */
 Components.Vim.Cursor.position.end;
+/** @type String */
+Components.Vim.Cursor.rawLine;