penguin/AstroJS

Javascript framework for my blog

commit bd35ed56b1ab9e605eea45b57becec6956178ada

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-13T18:15:24Z
subjectj for collapsed line ( partial )
commit bd35ed56b1ab9e605eea45b57becec6956178ada
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-13T18:15:24Z

    j for collapsed line ( partial )
---
 botanjs/src/Components/Vim/Cursor.js     | 55 +++++++++++++++++++++---
 botanjs/src/Components/Vim/LineBuffer.js | 14 +++---
 botanjs/src/Components/Vim/LineFeeder.js | 74 ++++++++++++++++++++++++--------
 botanjs/src/Components/Vim/StatusBar.js  |  3 +-
 botanjs/src/Components/Vim/VimArea.js    | 44 ++++++++++---------
 botanjs/src/Components/Vim/_this.js      | 20 +++++++--
 6 files changed, 154 insertions(+), 56 deletions(-)

diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index 4ce90fa..0fb6284 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -69,7 +69,7 @@
 		/** @type {Components.Vim.LineFeeder} */
 		this.feeder = feeder;
 
-		this.cols = feeder.lineBuffers[0].cols;
+		this.cols = feeder.firstBuffer.cols;
 
 		// The preferred X position
 		this.pX = 0;
@@ -136,6 +136,7 @@
 	Cursor.prototype.updatePosition = function()
 	{
 		this.P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
+		this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
 	};
 
 	Cursor.prototype.moveY = function( d )
@@ -143,16 +144,42 @@
 		var Y = this.Y;
 
 		Y += d;
-		if( Y < 0 ) Y = 0;
-
-		if( this.feeder.moreAt < Y )
+		if( Y < 0 )
+		{
+			Y = 0;
+		}
+		else if( this.feeder.moreAt < Y )
 		{
-			this.feeder.pan( undefined, Y - this.feeder.moreAt );
+			var feeder = this.feeder;
+			var lastLine = feeder.lastBuffer.lineNum;
+
+			var i = 0;
+			while( true )
+			{
+				feeder.pan( undefined, Y - feeder.moreAt + i );
+
+				// If it is the same line we keep scrolling it
+				// until the entire line cosumes the screen
+				if( feeder.lastBuffer.lineNum == lastLine )
+				{
+					i ++;
+				}
+				else break;
+			}
+
+			for( i = 0, line = feeder.firstBuffer;
+				line != feeder.lastBuffer;
+				line = line.next )
+			{
+				if( line.br ) i ++;
+				if( line.lineNum == Y ) break;
+			}
 
+			this.Y = i;
 			// Keep original position after panning
 			this.moveX();
 			this.updatePosition();
-			this.refresh();
+
 			return;
 		}
 
@@ -162,6 +189,21 @@
 		this.updatePosition();
 	};
 
+	Cursor.prototype.getLine = function()
+	{
+		var feeder = this.feeder;
+		var line = feeder.firstBuffer;
+		for( var i = 0;
+			line != feeder.lastBuffer;
+			line = line.next )
+		{
+			if( line.br ) i ++;
+			if( this.Y == i ) break;
+		}
+
+		return line;
+	};
+
 	__readOnly( Cursor.prototype, "position", function()
 	{
 		return {
@@ -170,6 +212,5 @@
 		};
 	} );
 
-
 	ns[ NS_EXPORT ]( EX_CLASS, "Cursor", Cursor );
 })();
diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js
index ff54620..ed612a6 100644
--- a/botanjs/src/Components/Vim/LineBuffer.js
+++ b/botanjs/src/Components/Vim/LineBuffer.js
@@ -19,6 +19,7 @@
 		this.next = nextLineBuffer;
 		this.br = false;
 		this.placeholder = true;
+		this.lineNum = 0;
 
 		if( nextLineBuffer )
 		{
@@ -26,14 +27,15 @@
 		}
 	};
 
-	LineBuffer.prototype.Push = function( content, wrap )
+	LineBuffer.prototype.Push = function( content, wrap, n )
 	{
+		this.lineNum = n;
 		if( content == undefined || content === "" )
 		{
 			this.content = "~";
 			this.br = true;
 			this.placeholder = true;
-			if( this.next ) this.next.Push( content, wrap );
+			if( this.next ) this.next.Push( content, wrap, n + 1 );
 			return;
 		}
 
@@ -42,9 +44,10 @@
 		var line = "";
 		var br = false;
 
+		var i = 0;
 		if( wrap )
 		{
-			for( var i = 0; i < this.cols; i ++ )
+			for( ; i < this.cols; i ++ )
 			{
 				var c = content[i];
 				if( c === undefined ) break;
@@ -62,7 +65,7 @@
 		else
 		{
 			br = true;
-			for( var i = 0; true; i ++ )
+			for( ; true; i ++ )
 			{
 				var c = content[i];
 				if( c === undefined ) break;
@@ -83,7 +86,7 @@
 		if( this.next )
 		{
 			this.next.br = br;
-			this.next.Push( content.substr( i ), wrap );
+			this.next.Push( content.substr( i ), wrap, br ? n + 1 : n );
 		}
 
 		this.content = line;
@@ -106,6 +109,5 @@
 		return lines;
 	} );
 
-
 	ns[ NS_EXPORT ]( EX_CLASS, "LineBuffer", LineBuffer );
 })();
diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
index 7725443..3edc1b7 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -21,12 +21,12 @@
 	{
 		var lineBuffers = [];
 
-		// Last line
-		lineBuffers[ rows - 1 ] = new LineBuffer( cols );
+		// Last line, hidden buffer that won't be rendered
+		this.__xBuffer = lineBuffers[ rows ] = new LineBuffer( cols );
 
-		for( var i = rows - 2; 0 <= i; i -- )
+		for( var i = rows - 1; 0 <= i; i -- )
 		{
-			lineBuffers[i] = new LineBuffer( cols, lineBuffers[ i + 1 ] );
+			lineBuffers[ i ] = new LineBuffer( cols, lineBuffers[ i + 1 ] );
 		}
 
 		this.lineBuffers = lineBuffers;
@@ -41,19 +41,23 @@
 
 		this.__clseLine = null;
 		this.__moreAt = -1;
+		this.__rows = rows;
+
+		this.__wrap = true;
 	};
 
 	Feeder.prototype.init = function( content, wrap )
 	{
-		if( wrap == undefined ) wrap = true;
-		if( this.lineBuffers.length )
-		{
-			this.lineBuffers[0].Push( content, wrap ); 
-		}
+		this.content = content;
+		this.setWrap( wrap );
+
+		this.firstBuffer.Push( content, this.__wrap, 0 ); 
 	};
 
-	Feeder.prototype.wrap = function( setwrap )
+	Feeder.prototype.setWrap = function( wrap )
 	{
+		if( wrap == undefined ) return;
+		this.__wrap = wrap;
 	};
 
 	Feeder.prototype.setRender = function( placeholder )
@@ -96,10 +100,10 @@
 		var buffs = this.lineBuffers;
 
 		if( start == undefined ) start = 0;
-		else if( buffs.length < start ) return "";
+		else if( this.__rows < start ) return "";
 
-		if( length == undefined || ( buffs.length - start ) < length ) 
-			length = buffs.length - start;
+		if( length == undefined || ( this.__rows - start ) < length ) 
+			length = this.rows - start;
 
 		if( length == 0 ) return "";
 
@@ -111,16 +115,40 @@
 		if( dX == undefined ) dX = 0;
 		if( dY == undefined ) dY = 0;
 
+		if( dX == 0 && dY == 0 ) return;
+
 		var X = this.panX + dX;
 		var Y = this.panY + dY;
 
-		// this.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+		var f = this.content.indexOf( "\n" );
+		var i = 1;
+
+		while( f != - 1 && i < Y )
+		{
+			i ++;
+			f = this.content.indexOf( "\n", f + 1 );
+		}
+
+		this.firstBuffer.Push(
+			this.content.substr( f + 1 )
+			, this.__wrap, i );
+
+		this.panX = X;
+		this.panY = Y;
 	};
 
+	__readOnly( Feeder.prototype, "firstBuffer", function() {
+		return this.lineBuffers[ 0 ];
+	} );
+
+	__readOnly( Feeder.prototype, "lastBuffer", function() {
+		return this.lineBuffers[ this.__rows - 1 ];
+	} );
+
 	__readOnly( Feeder.prototype, "moreAt", function() {
 		if( 0 < this.__moreAt ) return this.__moreAt;
 
-		var line = this.lineBuffers[0];
+		var line = this.firstBuffer;
 		if( line.placeholder ) return 0;
 
 		var i = 0;
@@ -136,15 +164,25 @@
 
 	__readOnly( Feeder.prototype, "lineStat", function() {
 		var X = this.cursor.X;
-		return ( this.cursor.Y + this.panY + 1 ) + "," + X + "-" + ( X );
+		return ( this.cursor.getLine().lineNum + 1 ) + "," + X + "-" + ( X );
 	} );
 
 	__readOnly( Feeder.prototype, "docPos", function() {
-		return "Top";
+		var pos = "ALL";
+
+		if( this.panY == 0 )
+		{
+			if( this.__clseLine || !this.EOF )
+			{
+				pos = "TOP";
+			}
+		}
+
+		return pos;
 	} );
 
 	__readOnly( Feeder.prototype, "linesOccupied", function() {
-		var line = this.lineBuffers[0];
+		var line = this.firstBuffer;
 		if( line.placeholder ) return 0;
 
 		var i = 0;
diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js
index 9aa4535..20424c8 100644
--- a/botanjs/src/Components/Vim/StatusBar.js
+++ b/botanjs/src/Components/Vim/StatusBar.js
@@ -1,4 +1,5 @@
-(function(){ var ns = __namespace( "Components.Vim" );
+(function(){
+	var ns = __namespace( "Components.Vim" );
 
 	/** @type {Dandelion} */
 	var Dand                                    = __import( "Dandelion" );
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 0cea4d7..bf3105b 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -19,6 +19,8 @@
 	/** @type {Components.Vim.StatusBar} */
 	var StatusBar = ns[ NS_INVOKE ]( "StatusBar" );
 
+	var mesg = ns[ NS_INVOKE ]( "Message" );
+
 	var KeyHandler = function( sender, handler )
 	{
 		return function( e )
@@ -87,16 +89,6 @@
 			case 112: // F1, help
 		}
 
-		var sfeeder = sender.statusFeeder;
-		var statusBar = sender.statusBar;
-
-		sfeeder.init( statusBar.statusText );
-		sender.stage.element.value =
-			cfeeder.render( 0, sender.rows - sfeeder.linesOccupied )
-			+ "\n" + sfeeder.render();
-
-		sender.__blink = false;
-		sender.select( cfeeder.cursor.position );
 	};
 
 	/* stage @param {Dandelion.IDOMElement} */
@@ -130,8 +122,7 @@
 		stage.addEventListener( "Blur", function() { _self.__active = false; } );
 
 		// Init
-		this.content = element.value;
-		this.VisualizeVimFrame();
+		this.VisualizeVimFrame( element.value );
 	};
 
 	VimArea.prototype.startInput = function( mode )
@@ -150,7 +141,7 @@
 		}
 	};
 
-	VimArea.prototype.VisualizeVimFrame = function()
+	VimArea.prototype.VisualizeVimFrame = function( content )
 	{
 		var _self = this;
 
@@ -161,7 +152,7 @@
 		// Content feeder
 		var cfeeder = new LineFeeder( r, c );
 
-		cfeeder.init( this.content );
+		cfeeder.init( content );
 
 		// Status feeder
 		sfeeder = new LineFeeder( r, c );
@@ -174,18 +165,25 @@
 		});
 
 		statusBar.stamp( -3, function(){
-			return cfeeder.docPos;
+			return mesg( cfeeder.docPos );
 		} );
 
 		sfeeder.init( statusBar.statusText );
 
-		element.value =
-			cfeeder.render( 0, r - sfeeder.linesOccupied )
-			+ "\n" + sfeeder.render();
-
-		cfeeder.dispatcher.addEventListener( "VisualUpdate", function()
+		var Update = function()
 		{
-		} );
+			sfeeder.init( statusBar.statusText );
+
+			element.value =
+				cfeeder.render( 0, r - sfeeder.linesOccupied )
+				+ "\n" + sfeeder.render();
+
+			_self.__blink = false;
+			_self.select( cfeeder.cursor.position );
+		};
+
+		cfeeder.dispatcher.addEventListener( "VisualUpdate", Update );
+		Update();
 
 		this.contentFeeder = cfeeder;
 		this.statusFeeder = sfeeder;
@@ -204,5 +202,9 @@
 		}, 600 );
 	};
 
+	__readOnly( VimArea.prototype, "content", function() {
+		return this.contentFeeder.content;
+	} );
+
 	ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea );
 })();
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index d61f8fc..d45751f 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -30,15 +30,29 @@
 		"E486": "E486: Pattern not found: %1"
 	};
 
-	var Message = function( key )
+	var GetString = function( arr, key, restArgs )
 	{
-		var restArgs = Array.prototype.slice.apply( arguments, 1 );
+		if( arr[ key ] == undefined ) return key;
+
 		var i = 0;
-		return messages[ key ].replace( /%\d+/g, function( e )
+		return arr[ key ].replace( /%\d+/g, function( e )
 		{
 			return restArgs[ i ++ ];
 		} );
 	};
 
+	var Message = function( key )
+	{
+		var restArgs = Array.prototype.slice.call( arguments, 1 );
+		return GetString( messages, key, restArgs );
+	};
+
+	var Error = function( key )
+	{
+		var restArgs = Array.prototype.slice.call( arguments, 1 );
+		return GetString( errors, key, restArgs );
+	};
+
 	ns[ NS_EXPORT ]( EX_FUNC, "Message", Message );
+	ns[ NS_EXPORT ]( EX_FUNC, "Error", Error );
 })();