penguin/AstroJS

Javascript framework for my blog

commit af2da6e023b43d2049e5c3490d7985dc61bdedd3

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-31T15:37:44Z
subjectAdded YANK
commit af2da6e023b43d2049e5c3490d7985dc61bdedd3
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-31T15:37:44Z

    Added YANK
---
 botanjs/src/Components/Vim/Actions/DELETE.js       |  24 ++--
 botanjs/src/Components/Vim/Actions/PUT.js          |  30 ++++-
 botanjs/src/Components/Vim/Actions/YANK.js         | 136 ++++++++++++++++++++-
 botanjs/src/Components/Vim/Controls.js             |   4 +
 botanjs/src/Components/Vim/State/Registers.js      |  33 +++--
 botanjs/src/Components/Vim/_this.js                |   5 +-
 .../src/externs/Components.Vim.State.Registers.js  |   8 +-
 7 files changed, 207 insertions(+), 33 deletions(-)

diff --git a/botanjs/src/Components/Vim/Actions/DELETE.js b/botanjs/src/Components/Vim/Actions/DELETE.js
index 1f05cbb..16daab5 100644
--- a/botanjs/src/Components/Vim/Actions/DELETE.js
+++ b/botanjs/src/Components/Vim/Actions/DELETE.js
@@ -10,6 +10,7 @@
 	var Stack                                  = __import( "Components.Vim.State.Stack" );
 
 	var Mesg = __import( "Components.Vim.Message" );
+	var beep = __import( "Components.Vim.Beep" );
 
 	var occurence = __import( "System.utils.Perf.CountSubstr" );
 
@@ -21,13 +22,15 @@
 		this.__nline = 0;
 		this.__startX = Cursor.aPos;
 		this.__panY = this.__cursor.feeder.panY;
+
+		Cursor.suppressEvent();
 	};
 
 	DELETE.prototype.allowMovement = true;
 
 	DELETE.prototype.dispose = function()
 	{
-
+		this.__cursor.unsuppressEvent();
 	};
 
 	DELETE.prototype.handler = function( e, sp )
@@ -43,6 +46,7 @@
 		var feeder = cur.feeder;
 
 		var Triggered = false;
+		var newLine = false;
 
 		if( sp == undefined )
 		{
@@ -50,8 +54,6 @@
 
 			sp = this.__startX;
 
-			cur.suppressEvent();
-
 			var currAp = cur.aPos;
 			if( this.__startX != currAp )
 			{
@@ -73,6 +75,7 @@
 				// Remove the current and the following line
 				else if( e.kMap( "j" ) )
 				{
+					newLine = true;
 					cur.lineEnd( true );
 					sp = cur.aPos;
 					cur.moveY( -1 );
@@ -82,6 +85,7 @@
 				// Remove the current and the preceding line
 				else if( e.kMap( "k" ) )
 				{
+					newLine = true;
 					cur.moveY( 1 );
 					cur.lineEnd( true );
 					sp = cur.aPos;
@@ -102,6 +106,7 @@
 			{
 				if( e.kMap( "d" ) )
 				{
+					newLine = true;
 					cur.lineEnd( true );
 					sp = cur.aPos;
 					cur.lineStart();
@@ -124,12 +129,10 @@
 				}
 				else
 				{
-					cur.unsuppressEvent();
-					return false;
+					beep();
+					return true;
 				}
 			}
-
-			cur.unsuppressEvent();
 		}
 
 		var c = feeder.content;
@@ -144,7 +147,7 @@
 		}
 
 		var removed = c.substring( s, e + 1 );
-		reg.change( removed );
+		reg.change( removed, newLine );
 
 		this.__nline = occurence( removed, "\n" );
 
@@ -156,7 +159,6 @@
 				? this.__panY - feeder.panY
 				: undefined
 		);
-
 		cur.moveTo( s );
 
 		var stator = new Stator( cur, s );
@@ -165,9 +167,7 @@
 		c = c[ e + 1 ];
 		if( c == "\n" || c == undefined )
 		{
-			cur.suppressEvent();
 			cur.moveX( -1 );
-			cur.unsuppressEvent();
 		}
 
 		var f = stator.save( 0, removed );
@@ -186,7 +186,7 @@
 	{
 		if( this.__nline )
 		{
-			return Mesg( "LINE_FEWER", this.__nline );
+			return Mesg( "LINES_FEWER", this.__nline );
 		}
 
 		return "";
diff --git a/botanjs/src/Components/Vim/Actions/PUT.js b/botanjs/src/Components/Vim/Actions/PUT.js
index 164899b..81ff721 100644
--- a/botanjs/src/Components/Vim/Actions/PUT.js
+++ b/botanjs/src/Components/Vim/Actions/PUT.js
@@ -16,14 +16,15 @@
 	{
 		/** @type {Components.Vim.Cursor} */
 		this.__cursor = Cursor;
-		this.__stator = new Stator( Cursor );
 		this.__msg = "";
+		Cursor.suppressEvent();
 	};
 
 	PUT.prototype.allowMovement = false;
 
 	PUT.prototype.dispose = function()
 	{
+		this.__cursor.unsuppressEvent();
 	};
 
 	PUT.prototype.handler = function( e )
@@ -42,38 +43,55 @@
 		var cur = this.__cursor;
 		var feeder = cur.feeder;
 
+		var newLine = cput.newLine;
+		if( newLine )
+		{
+			cur.moveY( 1 );
+			cur.lineStart();
+		}
+
+		var stator = new Stator( cur );
 		var aP = cur.aPos;
 
 		feeder.content = feeder.content.substring( 0, aP )
 			+ cput
 			+ feeder.content.substring( aP );
 
-		cur.suppressEvent();
 		feeder.pan();
 
 		cur.moveTo( 0 < nLines ? aP : aP + clen, true );
 
 		var stack = new Stack();
 
-		stack.store( this.__stator.save( clen, "" ) );
+		if( newLine )
+		{
+			var f = stator.save( clen, "" );
+			stack.store( function()
+			{
+				f();
+				cur.moveY( -1 );
+			} );
+		}
+		else
+		{
+			stack.store( stator.save( clen, "" ) );
+		}
 		cur.rec.record( stack );
 
 		this.__put = cput;
 
 		if( nLines )
 		{
-			this.__msg = Mesg( "LINE_MORE", nLines );
+			this.__msg = Mesg( "LINES_MORE", nLines );
 		}
 
 		cur.moveX( -1 );
-		cur.unsuppressEvent();
 
 		return true;
 	};
 
 	PUT.prototype.getMessage = function()
 	{
-		console.log( this.__msg );
 		return this.__msg;
 	};
 
diff --git a/botanjs/src/Components/Vim/Actions/YANK.js b/botanjs/src/Components/Vim/Actions/YANK.js
index ba987d7..12f7a5c 100644
--- a/botanjs/src/Components/Vim/Actions/YANK.js
+++ b/botanjs/src/Components/Vim/Actions/YANK.js
@@ -1,31 +1,161 @@
 (function(){
 	var ns = __namespace( "Components.Vim.Actions" );
 
+	/** @type {System.Debug} */
+	var debug = __import( "System.Debug" );
+
 	var Mesg = __import( "Components.Vim.Message" );
+	var beep = __import( "Components.Vim.Beep" );
+
+	var occurence = __import( "System.utils.Perf.CountSubstr" );
 
 	/** @type {Components.Vim.Cursor.IAction} */
 	var YANK = function( Cursor )
 	{
 		/** @type {Components.Vim.Cursor} */
 		this.__cursor = Cursor;
+		this.__startX = Cursor.aPos;
+		this.__msg = "";
+
+		Cursor.suppressEvent();
 	};
 
 	YANK.prototype.allowMovement = true;
 
 	YANK.prototype.dispose = function()
 	{
-
+		this.__cursor.unsuppressEvent();
 	};
 
-	YANK.prototype.handler = function( e )
+	YANK.prototype.handler = function( e, sp )
 	{
 		e.preventDefault();
 
+		if( e.ModKeys || e.kMap( "i" ) ) return;
+
+		/** @type {Components.Vim.State.Registers} */
+		var reg = e.target.registers;
+
+		var cur = this.__cursor;
+		var feeder = cur.feeder;
+
+		var Triggered = false;
+
+		var newLine = false;
+		if( sp == undefined )
+		{
+			Triggered = true;
+
+			sp = this.__startX;
+
+			var currAp = cur.aPos;
+			if( this.__startX != currAp )
+			{
+				// Remove to start
+				if( e.kMap( "^" ) )
+				{
+					sp --;
+				}
+				// Remove char in cursor
+				else if( e.kMap( "l" ) )
+				{
+					cur.moveX( -1 );
+				}
+				// Remove char before cursor
+				else if( e.kMap( "h" ) )
+				{
+					sp = currAp;
+				}
+				// Remove the current and the following line
+				else if( e.kMap( "j" ) )
+				{
+					newLine = true;
+					cur.lineEnd( true );
+					sp = cur.aPos;
+					cur.moveY( -1 );
+					cur.lineStart();
+					this.__startX = cur.aPos;
+				}
+				// Remove the current and the preceding line
+				else if( e.kMap( "k" ) )
+				{
+					newLine = true;
+					cur.moveY( 1 );
+					cur.lineEnd( true );
+					sp = cur.aPos;
+					cur.moveY( -1 );
+					cur.lineStart();
+				}
+				else if( this.__startX < currAp )
+				{
+					// Swap the movement
+					// This is to move the REDO / UNDO Cursor
+					// position to the earlier position
+					sp = currAp;
+					cur.moveTo( this.__startX );
+				}
+			}
+			// Remove the current line
+			else
+			{
+				if( e.kMap( "y" ) )
+				{
+					newLine = true;
+					cur.lineEnd( true );
+					sp = cur.aPos;
+					cur.lineStart();
+				}
+				else if( e.range )
+				{
+					sp = e.range.close;
+					cur.moveTo( e.range.open, true );
+				}
+				else if( e.kMap( "^" ) )
+				{
+					// Do nothing as nothing can be removed
+					// since there is no successful movement
+					return true;
+				}
+				// this is the same as kMap( "h" ) above
+				else if( e.kMap( "$" ) )
+				{
+					sp = cur.aPos;
+				}
+				else
+				{
+					beep();
+					return true;
+				}
+			}
+		}
+
+		var s = sp;
+		var e = cur.aPos;
+
+		if( e < s )
+		{
+			s = cur.aPos;
+			e = sp;
+		}
+
+		cur.moveTo( s );
+
+		var yText = cur.feeder.content.substring( s, e + 1 );
+
+		reg.yank( yText, newLine );
+
+		var nline = occurence( yText, "\n" );
+		if( nline )
+		{
+			this.__msg = Mesg( "LINES_YANKED", nline );
+		}
+
+		return Triggered;
 	};
 
 	YANK.prototype.getMessage = function()
 	{
-		return "<TODO> YANK COMMAND";
+		return this.__msg;
 	};
 
 	ns[ NS_EXPORT ]( EX_CLASS, "YANK", YANK );
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 522e35d..1163433 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -189,9 +189,13 @@
 			case CTRL + R: // Redo
 				ccur.openRunAction( "REDO", e );
 				break;
+
 			case D: // Del with motion
 				ccur.openAction( "DELETE" );
 				break;
+			case Y: // Yank with motion
+				ccur.openAction( "YANK" );
+				break;
 
 			case P: // Put
 				ccur.suppressEvent();
diff --git a/botanjs/src/Components/Vim/State/Registers.js b/botanjs/src/Components/Vim/State/Registers.js
index 48ca4a3..ec6335b 100644
--- a/botanjs/src/Components/Vim/State/Registers.js
+++ b/botanjs/src/Components/Vim/State/Registers.js
@@ -15,25 +15,41 @@
 */
 	var ns = __namespace( "Components.Vim.State" );
 
+	var Register = function( str, n )
+	{
+		this.__str = str + "";
+		this.newLine = Boolean( n );
+	};
+
+	Register.prototype.newLine = false;
+
+	Register.prototype.toString = function() { return this.__str; };
+	Register.prototype.indexOf = function( a, b ) { return this.__str.indexOf( a, b ); };
+
+	__readOnly( Register.prototype, "length", function() { return this.__str.length; } );
+
+
 	var Registers = function()
 	{
 		this.__registers = {};
 	};
 
-	Registers.prototype.unnamed = function( str )
+	Registers.prototype.__unnamed = function( reg )
 	{
-		this.__registers[ "\"" ] = str;
+		this.__registers[ "\"" ] = reg;
 	};
 
-	Registers.prototype.yank = function( str )
+	Registers.prototype.yank = function( str, newLine )
 	{
-		this.unnamed( str );
-		this.__registers[ 0 ] = str;
+		var reg = new Register( str, newLine );
+		this.__unnamed( reg );
+		this.__registers[ 0 ] = reg;
 	};
 
-	Registers.prototype.change = function( str )
+	Registers.prototype.change = function( str, newLine )
 	{
-		this.unnamed( str );
+		var reg = new Register( str, newLine );
+		this.__unnamed( reg );
 		var r = this.__registers;
 		for( var i = 9; 1 < i; i -- )
 		{
@@ -43,7 +59,7 @@
 			}
 		}
 
-		r[ 1 ] = str;
+		r[ 1 ] = reg;
 	};
 
 	Registers.prototype.get = function( r )
@@ -55,4 +71,5 @@
 	};
 
 	ns[ NS_EXPORT ]( EX_CLASS, "Registers", Registers );
+
 })();
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 8a5b199..e387304 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -18,8 +18,9 @@
 		, "UNDO_LIMIT": "Already at oldest change"
 		, "REDO_LIMIT": "Already at newest change"
 
-		, "LINE_FEWER": "%1 fewer lines"
-		, "LINE_MORE": "%1 more lines"
+		, "LINES_FEWER": "%1 fewer line(s)"
+		, "LINES_MORE": "%1 more line(s)"
+		, "LINES_YANKED": "%1 line(s) yanked"
 	};
 
 	var errors = {
diff --git a/botanjs/src/externs/Components.Vim.State.Registers.js b/botanjs/src/externs/Components.Vim.State.Registers.js
index 75b9c13..61bdfc7 100644
--- a/botanjs/src/externs/Components.Vim.State.Registers.js
+++ b/botanjs/src/externs/Components.Vim.State.Registers.js
@@ -5,5 +5,9 @@ Components.Vim.State.Registers = function(){};
 Components.Vim.State.Registers.change;
 /** @type Function */
 Components.Vim.State.Registers.yank;
-/** @type Function */
-Components.Vim.State.Registers.unnamed;
+
+/** @constructor */
+Components.Vim.State.Register = function(){};
+
+/** @type Boolean */
+Components.Vim.State.Register.newLine;