penguin/AstroJS

Javascript framework for my blog

commit 8769e69f35aa3117cf1d325ae4f211fef73c84e2

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-19T23:52:44Z
subjectInsert mode line break bug fix
commit 8769e69f35aa3117cf1d325ae4f211fef73c84e2
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-19T23:52:44Z

    Insert mode line break bug fix
---
 botanjs/src/Components/Vim/Actions/INSERT.js | 25 ++++++---
 botanjs/src/Components/Vim/Controls.js       | 79 ++++++++++++++++------------
 botanjs/src/Components/Vim/Cursor.js         | 72 ++++++++++---------------
 botanjs/src/Components/Vim/LineFeeder.js     |  2 +-
 botanjs/src/Components/Vim/VimArea.js        |  6 ++-
 botanjs/src/Components/Vim/_this.js          |  1 +
 6 files changed, 99 insertions(+), 86 deletions(-)

diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js
index d97d34c..e6d4615 100644
--- a/botanjs/src/Components/Vim/Actions/INSERT.js
+++ b/botanjs/src/Components/Vim/Actions/INSERT.js
@@ -36,13 +36,21 @@
 	INSERT.prototype.__saveCur = function()
 	{
 		var c = this.__cursor;
-		return {
+		var obj = {
 			p: c.P
 			, x: c.X
 			, y: c.Y
 			, px: c.feeder.panX
 			, py: c.feeder.panY
 		};
+
+		if( 0 < obj.x )
+		{
+			obj.p -= 1;
+			obj.x -= 1;
+		}
+
+		return obj;
 	}
 
 	INSERT.prototype.dispose = function()
@@ -186,20 +194,23 @@
 			+ inputChar
 			+ feeder.content.substring( f );
 
-		feeder.pan();
-		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
-
-		this.__rec( inputChar );
-
 		if( inputChar == "\n" )
 		{
+			feeder.softReset();
+			feeder.pan();
 			cur.moveY( 1 );
 			cur.lineStart();
 		}
 		else
 		{
-			cur.moveX( 1 );
+			feeder.pan();
+			cur.moveX( 1, false, true );
 		}
+
+		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+
+		this.__rec( inputChar );
+
 	};
 
 	INSERT.prototype.getMessage = function()
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 5e4d892..7f37de7 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -19,6 +19,12 @@
 	var U = 85; var V = 86; var W = 87; var X = 88; var Y = 89;
 	var Z = 90;
 
+	var ESC = 27;
+
+	var F1 = 112; var F2 = 113; var F3 = 114; var F4 = 115; var F5 = 116;
+	var F6 = 117; var F7 = 118; var F8 = 119; var F9 = 120; var F10 = 121;
+	var F11 = 122; var F12 = 123;
+
 	var Controls = function( vimArea )
 	{
 		/** @type {Components.Vim.VimArea} */
@@ -77,7 +83,7 @@
 		// Neve capture these keys
 		if( e.altKey
 			// F2 - F12
-			|| ( 112 < e.keyCode && e.keyCode < 124 )
+			|| ( F1 < e.keyCode && e.keyCode < 124 )
 		) return;
 
 		var vArea = this.__vimArea;
@@ -85,7 +91,7 @@
 		var cfeeder = vArea.contentFeeder;
 
 		// Esc OR Ctrl + c
-		var Escape = e.keyCode == 27 || ( e.ctrlKey && e.keyCode == 67 );
+		var Escape = e.keyCode == ESC || ( e.ctrlKey && e.keyCode == C );
 
 		// Clear the keychains in combo commands
 		if( Escape && this.__keyChains.length )
@@ -141,26 +147,10 @@
 			}
 		};
 
+		var ActionHandled = true;
+		// Action Commands
 		switch( kCode )
 		{
-			// Cursor movements
-			case BACKSPACE: // Backspace, go back 1 char, regardless of line
-				cMoveX( -1, true );
-				break;
-			case H: // Left
-				cMoveX( -1 );
-				break;
-			case L: // Right
-				cMoveX( 1 );
-				break;
-			case K: // Up
-				cMoveY( -1 );
-				break;
-			case J: // Down
-				cMoveY( 1 );
-				break;
-
-			// Insert
 			case SHIFT + A: // Append at the line end
 				ccur.lineEnd();
 			case A: // Append
@@ -182,34 +172,57 @@
 				break;
 			case SHIFT + I: // Append before the line start, after spaces
 				break;
-
-			case SHIFT + G: // Goto last line
-				ccur.moveY( Number.MAX_VALUE );
-				ccur.moveX( Number.MAX_VALUE, true );
+			case SHIFT + J: // Join lines
 				break;
-			// remove characters
-			case X: // Remove in cursor
+			case SHIFT + K: // Find the manual entry
 				break;
-			case SHIFT + X: // Remove before cursor
+
+			case F1: // F1, help
 				break;
+			default:
+				ActionHandled = false;
+		}
+
+		if( ActionHandled ) return;
+
+		// Cursor Commands
+		switch( kCode )
+		{
+			case BACKSPACE: cMoveX( -1, true ); break; // Backspace, go back 1 char, regardless of line
+			case H: cMoveX( -1 ); break; // Left
+			case L: cMoveX( 1 ); break; // Right
+			case K: cMoveY( -1 ); break; // Up
+			case J: cMoveY( 1 ); break; // Down
 
 			case SHIFT + H: // First line buffer
 				break;
 			case SHIFT + L: // Last line buffer
 				break;
+			case SHIFT + _6: // ^, Start
+				ccur.lineStart();
+				break;
 			case SHIFT + _4: // $, End
 				ccur.lineEnd();
 				break;
-			case SHIFT + _5: // %, Find next item
+			case SHIFT + G: // Goto last line
+				ccur.moveY( Number.MAX_VALUE );
+				ccur.moveX( Number.MAX_VALUE, true );
 				break;
-			case SHIFT + _6: // ^, Start
-				ccur.lineStart();
+
+			case SHIFT + _5: // %, Find next item
 				break;
-			case SHIFT + J: // Join lines
+		}
+
+
+		// Integrated commands
+		switch( kCode )
+		{
+			case V: // Visual
+				ccur.openAction( "VISUAL" );
 				break;
-			case SHIFT + K: // manual entry
+			case SHIFT + V: // Visual line
+				ccur.openAction( "VISUAL_LINE" );
 				break;
-			case 112: // F1, help
 		}
 
 	};
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index b57650f..f4b6d9b 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -9,26 +9,6 @@
 
 	var Actions = __import( "Components.Vim.Actions.*" );
 
-	var GetLine = function( buffs, l )
-	{
-		/** @type {Components.Vim.LineBuffer} */
-		var LineHead = buffs[0];
-		l ++;
-
-		for( var i = 0, line = LineHead;
-			line && i < l; i ++ )
-		{
-			LineHead = line;
-			while( line )
-			{
-				line = line.next;
-				if( line.br ) break;
-			}
-		}
-
-		return LineHead;
-	};
-
 	var LineOffset = function( buffs, l )
 	{
 		/** @type {Components.Vim.LineBuffer} */
@@ -123,7 +103,7 @@
 		}
 
 		/** @type {Components.Vim.LineBuffer} */
-		var line = GetLine( buffs, this.Y );
+		var line = this.getLine();
 		var content = line.visualLines.join( "\n" );
 		var cLen = content.length;
 
@@ -211,35 +191,40 @@
 			{
 				var lastLine = feeder.lastBuffer.lineNum;
 				var lineShift = Y - feeder.moreAt;
+				var thisLine = this.getLine().lineNum;
 
-				i = lineShift;
-				while( !feeder.EOF )
+				if( !feeder.EOF )
+					feeder.pan( undefined, lineShift );
+
+				// if it turns out to be the same line
+				// before after panning
+				// we keep scrolling it ( panning )
+				// until the entire line cosumes the screen
+				while( !feeder.EOF && feeder.lastBuffer.lineNum == lastLine )
 				{
-					feeder.pan( undefined, i );
-
-					// if it turns out to be the same line
-					// before after panning
-					// we keep scrolling it ( panning )
-					// until the entire line cosumes the screen
-					if( feeder.lastBuffer.lineNum == lastLine )
-					{
-						i ++;
-					}
-					else break;
+					feeder.pan( undefined, 1 );
 				}
 
 				// The line number cursor need to be in
-				Y = lastLine + lineShift;
+				Y = thisLine + d;
 
+				i = this.Y;
+				this.Y = 0;
 				// Calculate the visual line position "i"
-				for( i = 0, line = feeder.firstBuffer;
-					line != feeder.lastBuffer;
-					line = line.next )
+				for( var line = this.getLine();
+					line && line.lineNum != Y && !line.placeholder;
+					this.Y ++, line = this.getLine() )
 				{
-					if( line.br ) i ++;
-					if( line.lineNum == Y || line.next.placeholder ) break;
 				}
 
+				i = this.Y;
+
+				// Check if this line is collapsed
+				if( !feeder.EOF && feeder.lastBuffer.next.lineNum == line.lineNum )
+				{
+					// If yes, step back to last visible line
+					i --;
+				}
 			}
 
 			this.Y = i;
@@ -301,15 +286,16 @@
 	{
 		var feeder = this.feeder;
 		var line = feeder.firstBuffer;
+		var eBuffer = feeder.lastBuffer.next;
 		for( var i = 0;
-			line != feeder.lastBuffer;
+			line != eBuffer;
 			line = line.next )
 		{
 			if( line.br ) i ++;
-			if( this.Y == i ) break;
+			if( this.Y == i ) return line;
 		}
 
-		return line;
+		return null;
 	};
 
 	// The absX for current Line
diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
index 7bedae0..e50f4ac 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -94,7 +94,7 @@
 		this.__softRender = function()
 		{
 			var line = _self.lineBuffers[ _self.__rStart ];
-			var steps = _self.__rLength;
+			var steps = _self.__rLength + 1;
 
 			for( var i = 0;
 				line && i < steps && ( line = line.next ) && placeholdCond( line );
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index b9a76e4..8452fab 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -92,7 +92,9 @@
 		// Content feeder
 		var cfeeder = new LineFeeder( cRange, c );
 
-		cfeeder.init( content );
+		// This "\n" fixes the last line "\n" not displaying
+		// it will be trimmed after saving
+		cfeeder.init( content + "\n" );
 
 		// Status can consumes up to full screen, I think
 		sfeeder = new LineFeeder( r, c );
@@ -147,7 +149,7 @@
 	};
 
 	__readOnly( VimArea.prototype, "content", function() {
-		return this.contentFeeder.content;
+		return this.contentFeeder.content.slice( 0, -1 );
 	} );
 
 	ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea );
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 5b263b9..04060da 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -5,6 +5,7 @@
 		"INSERT": "-- INSERT --"
 		, "REPLACE": "-- REPLACE --"
 		, "MORE": "-- MORE --"
+		, "VISUAL": "-- VISUAL  --"
 		, "VISLINE": "-- VISUAL LINE --"
 		, "WRITE": "\"%1\" %2L, %3C written"
 		, "CONTINUE": "Press ENTER or type command to continue"