penguin/AstroJS

Javascript framework for my blog

commit 2548970f3a77df69da1f463514dfdaa2e7beb7f3

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-13T12:26:26Z
subjectPartial nav of "jkhl$^"
commit 2548970f3a77df69da1f463514dfdaa2e7beb7f3
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-13T12:26:26Z

    Partial nav of "jkhl$^"
---
 botanjs/src/Components/Vim/Cursor.js     | 51 ++++++++++-------
 botanjs/src/Components/Vim/LineBuffer.js |  2 +-
 botanjs/src/Components/Vim/LineFeeder.js | 96 +++++++++++++++++++++++---------
 botanjs/src/Components/Vim/VimArea.js    | 27 ++++++++-
 botanjs/src/Components/Vim/_this.js      |  1 +
 5 files changed, 127 insertions(+), 50 deletions(-)

diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index b72ea1b..4ce90fa 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -37,42 +37,39 @@
 		/** @type {Components.Vim.LineBuffer} */
 		var offset = 0;
 
+		LineLoop:
 		for( var i = 0, line = buffs[0];
 			line && i < l; i ++ )
 		{
 			while( line )
 			{
-				if( line.br )
-				{
-					offset += line.prev.toString().length + 1;
-
-					// Empty line has a special space
-					if( line.content == "" ) offset ++;
+				if( line.next && line.next.placeholder )
+					break LineLoop;
 
+				if( line.next && line.next.br )
+				{
+					offset += line.toString().length + 1;
 					line = line.next;
 					break;
 				}
 				else
 				{
-					if( offset == 0 ) offset -= 1;
-
-					if( line.next && !line.next.br )
-						offset += line.cols + 1;
+					offset += line.cols + 1;
 				}
 
 				line = line.next;
 			}
 		}
 
-		debug.Info( offset );
-
 		return offset;
 	};
 
-	var Cursor = function( buffs )
+	var Cursor = function( feeder )
 	{
-		this.buffers = buffs;
-		this.cols = buffs[0].cols;
+		/** @type {Components.Vim.LineFeeder} */
+		this.feeder = feeder;
+
+		this.cols = feeder.lineBuffers[0].cols;
 
 		// The preferred X position
 		this.pX = 0;
@@ -98,7 +95,7 @@
 
 		if( !d ) d = 1;
 
-		var buffs = this.buffers;
+		var buffs = this.feeder.lineBuffers;
 
 		/** @type {Components.Vim.LineBuffer} */
 		var line = GetLine( buffs, this.Y );
@@ -133,18 +130,34 @@
 
 	Cursor.prototype.lineEnd = function()
 	{
-		/** @type {Components.Vim.LineBuffer} */
 		this.moveX( Number.MAX_VALUE );
 	};
 
 	Cursor.prototype.updatePosition = function()
 	{
-		this.P = this.X + LineOffset( this.buffers, this.Y );
+		this.P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
 	};
 
 	Cursor.prototype.moveY = function( d )
 	{
-		this.Y += d;
+		var Y = this.Y;
+
+		Y += d;
+		if( Y < 0 ) Y = 0;
+
+		if( this.feeder.moreAt < Y )
+		{
+			this.feeder.pan( undefined, Y - this.feeder.moreAt );
+
+			// Keep original position after panning
+			this.moveX();
+			this.updatePosition();
+			this.refresh();
+			return;
+		}
+
+		this.Y = Y;
+
 		this.moveX();
 		this.updatePosition();
 	};
diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js
index aa0360a..ff54620 100644
--- a/botanjs/src/Components/Vim/LineBuffer.js
+++ b/botanjs/src/Components/Vim/LineBuffer.js
@@ -24,7 +24,6 @@
 		{
 			nextLineBuffer.prev = this;
 		}
-
 	};
 
 	LineBuffer.prototype.Push = function( content, wrap )
@@ -32,6 +31,7 @@
 		if( content == undefined || content === "" )
 		{
 			this.content = "~";
+			this.br = true;
 			this.placeholder = true;
 			if( this.next ) this.next.Push( content, wrap );
 			return;
diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
index 2aba1f8..7725443 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -29,10 +29,18 @@
 			lineBuffers[i] = new LineBuffer( cols, lineBuffers[ i + 1 ] );
 		}
 
-		this.cursor = new Cursor( lineBuffers );
-
 		this.lineBuffers = lineBuffers;
+
+		this.panX = 0;
+		this.panY = 0;
+
 		this.setRender();
+
+		this.cursor = new Cursor( this );
+		this.dispatcher = new EventDispatcher();
+
+		this.__clseLine = null;
+		this.__moreAt = -1;
 	};
 
 	Feeder.prototype.init = function( content, wrap )
@@ -52,38 +60,35 @@
 	{
 		if( placeholder == undefined ) placeholder = true;
 
-		if( placeholder )
-		{
-			this.__render = function( line, steps )
-			{
-				var display = ( line == undefined ? "" : line ) + "";
+		var _self = this;
 
-				for( var i = 0;
-					line && i < steps && ( line = line.next );
-					i ++ )
-				{
-					display += "\n" + line;
-				}
+		var placeholdCond = placeholder
+			? function( line ) { return true; }
+			:  function( line ) { return !line.placeholder; }
+			;
 
-				return display;
-			};
-		}
-		else
+		this.__render = function( line, steps )
 		{
-			this.__render = function( line, steps )
-			{
-				var display = ( line == undefined ? "" : line ) + "";
+			var display = ( line == undefined ? "" : line ) + "";
 
-				for( var i = 0;
-					line && i < steps && ( line = line.next ) && !line.placeholder;
-					i ++ )
+			var atSpace = false
+			for( var i = 0;
+				line && i < steps && ( line = line.next ) && placeholdCond( line );
+				i ++ )
+			{
+				if( atSpace || ( line.br && steps < ( i + line.visualLines.length ) ) )
 				{
-					display += "\n" + line;
+					if( !atSpace ) _self.__clseLine = line;
+					atSpace = true;
+					display += "\n@";
+					continue;
 				}
 
-				return display;
-			};
-		}
+				display += "\n" + line;
+			}
+
+			return display;
+		};
 	}
 
 	Feeder.prototype.render = function( start, length )
@@ -101,6 +106,43 @@
 		return this.__render( buffs[ start ], length - 1 );
 	};
 
+	Feeder.prototype.pan = function( dX, dY )
+	{
+		if( dX == undefined ) dX = 0;
+		if( dY == undefined ) dY = 0;
+
+		var X = this.panX + dX;
+		var Y = this.panY + dY;
+
+		// this.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+	};
+
+	__readOnly( Feeder.prototype, "moreAt", function() {
+		if( 0 < this.__moreAt ) return this.__moreAt;
+
+		var line = this.lineBuffers[0];
+		if( line.placeholder ) return 0;
+
+		var i = 0;
+		do
+		{
+			if( this.__clseLine == line ) break;
+			if( line.br ) i ++;
+		}
+		while( line = line.next );
+
+		return ( this.__moreAt = i );
+	} );
+
+	__readOnly( Feeder.prototype, "lineStat", function() {
+		var X = this.cursor.X;
+		return ( this.cursor.Y + this.panY + 1 ) + "," + X + "-" + ( X );
+	} );
+
+	__readOnly( Feeder.prototype, "docPos", function() {
+		return "Top";
+	} );
+
 	__readOnly( Feeder.prototype, "linesOccupied", function() {
 		var line = this.lineBuffers[0];
 		if( line.placeholder ) return 0;
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 159a34f..0cea4d7 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -52,6 +52,7 @@
 		{
 			// Cursor movements
 			case 72: // h
+			case 8: // Backspace
 				cfeeder.cursor.moveX( -1 );
 				break;
 			case 74: // j
@@ -86,6 +87,14 @@
 			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 );
 	};
@@ -112,7 +121,13 @@
 		this.PosX = 1;
 		this.PosY = 1;
 
+		this.__active = false;
+
+		var _self = this;
+
 		stage.addEventListener( "KeyDown", KeyHandler( this, VimControls ) );
+		stage.addEventListener( "Focus", function() { _self.__active = true; } );
+		stage.addEventListener( "Blur", function() { _self.__active = false; } );
 
 		// Init
 		this.content = element.value;
@@ -125,6 +140,7 @@
 
 	VimArea.prototype.select = function( sel )
 	{
+		if( !this.__active ) return;
 		var textarea = this.stage.element;
 
 		if( sel )
@@ -154,12 +170,12 @@
 		// XXX: Placeholder
 		var statusBar = new StatusBar( c );
 		statusBar.stamp( -18, function(){
-			return "1,1-1";
+			return cfeeder.lineStat;
 		});
 
 		statusBar.stamp( -3, function(){
-			return "All";
-		});
+			return cfeeder.docPos;
+		} );
 
 		sfeeder.init( statusBar.statusText );
 
@@ -167,8 +183,13 @@
 			cfeeder.render( 0, r - sfeeder.linesOccupied )
 			+ "\n" + sfeeder.render();
 
+		cfeeder.dispatcher.addEventListener( "VisualUpdate", function()
+		{
+		} );
+
 		this.contentFeeder = cfeeder;
 		this.statusFeeder = sfeeder;
+		this.statusBar = statusBar;
 
 		this.__cursor = cfeeder.cursor;
 
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 5de456f..d61f8fc 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -16,6 +16,7 @@
 		"INSERT": "-- INSERT --"
 		, "REPLACE": "-- REPLACE --"
 		, "MORE": "-- MORE --"
+		, "VISLINE": "-- VISUAL LINE --"
 		, "WRITE": "\"%1\" %2L, %3C written"
 		, "CONTINUE": "Press ENTER or type command to continue"
 		, "SEARCH_HIT_BOTTOM": "Seach hit BOTTOM, contining at TOP"