penguin/AstroJS

Javascript framework for my blog

commit ce669c2cb625e2cd969157a38dc391460d7d7f4a

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-04-15T20:00:15Z
subjectLine shifting support
commit ce669c2cb625e2cd969157a38dc391460d7d7f4a
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-04-15T20:00:15Z

    Line shifting support
---
 botanjs/src/Components/Vim/Actions/SHIFT_LINES.js | 108 ++++++++++++++++++----
 botanjs/src/Components/Vim/Actions/VISUAL.js      |   6 ++
 botanjs/src/Components/Vim/Controls.js            |  26 +++++-
 botanjs/src/Components/Vim/_this.js               |   2 +
 4 files changed, 118 insertions(+), 24 deletions(-)

diff --git a/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js b/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
index 650c68e..1202b6c 100644
--- a/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
+++ b/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
@@ -62,12 +62,14 @@
 
 		var start = this.__slineNum;
 		var nline = this.__lines;
+		var indentMult = 1;
 
 		if( 1 < e.count )
 		{
 			nline += e.count;
 		}
 
+		// default: >>, <<, >l, <h
 		var end = start;
 
 		var shiftCount = 1;
@@ -81,30 +83,86 @@
 
 			if( this.__startX != currAp )
 			{
-				if( e.kMap( "h" ) || e.kMap( "l" ) ){}
-				else if( e.kMap( "j" ) )
+				if( currAp < sp )
 				{
-					end = start + nline;
+					sp = sp + currAp;
+					currAp = sp - currAp;
+					sp = sp - currAp;
 				}
-				else if( e.kMap( "k" ) )
-				{
-					start -= nline;
-				}
-				else // TODO: Dectect movement line count
+
+				start = end = 0;
+				for( var i = 0; i < currAp; i ++ )
 				{
+					if( feeder.content[ i ] == "\n" )
+					{
+						end ++;
+						if( i < sp )
+						{
+							start ++;
+						}
+					}
 				}
 			}
 			else
 			{
-				if( !( ( 0 < dir && ( e.kMap( ">" ) || e.kMap( "l" ) ) )
-					|| ( dir < 0 && ( e.kMap( "<" ) || e.kMap( "h" ) ) )
-				) )
+				if( e.range )
+				{
+					sp = e.range.close;
+
+					start = 1; end = -1;
+					for( var i = 0; i < sp; i ++ )
+					{
+						if( feeder.content[ i ] == "\n" )
+						{
+							end ++;
+							if( i < e.range.open )
+							{
+								start ++;
+							}
+						}
+					}
+
+					if( end == -1 )
+					{
+						start = end = 0;
+					}
+
+					if( end < start )
+					{
+						end = -- start;
+					}
+
+					indentMult = e.count;
+				}
+				else if( 0 < dir && ( e.kMap( ">" ) || e.kMap( "l" ) ) );
+				else if( dir < 0 && ( e.kMap( "<" ) || e.kMap( "h" ) ) );
+				else
 				{
 					beep();
 					return true;
 				}
 			}
 		}
+		// VISUAL Mode
+		else
+		{
+			start = 0;
+			for( var i = 0; i < sp; i ++ )
+			{
+				if( feeder.content[ i ] == "\n" ) start ++;
+			}
+
+			end = this.__slineNum;
+
+			indentMult = e.count;
+		}
+
+		if( end < start )
+		{
+			start = start + end;
+			end = start - end;
+			start = start - end;
+		}
 
 		// last "\n" padding
 		var c = feeder.content.slice( 0, -1 );
@@ -124,7 +182,7 @@
 				var spOccr = 0;
 
 				// Guess indent
-				var tabStat = {};
+				var tabStat = [];
 
 				for( var i = 0; i < l; i ++ )
 				{
@@ -146,6 +204,7 @@
 				var indentCLen = 0;
 				for( var i in tabStat )
 				{
+					i = Number( i );
 					var p = tabStat[ i ];
 					if( upperDiff < p )
 					{
@@ -179,13 +238,15 @@
 		var nLen = 0;
 
 		var started = false;
-		var indentTimes = 1;
 
 		var recStart = 0;
 
 		feeder.content = "";
 		nline = 0;
 
+		var indented = "";
+		for( var i = 0; i < indentMult; i ++ ) indented += indentChar;
+
 		for( var i = 0, j = 0; 0 <= i; i = c.indexOf( "\n", i ), j ++ )
 		{
 			i ++;
@@ -216,24 +277,24 @@
 				var indentedLine;
 				if( 0 < dir )
 				{
-					indentedLine = indentChar + line;
+					indentedLine = indented + line;
 				}
 				else
 				{
-					for( var si = 0, sj = 1; si < indentTimes; si ++ )
+					for( var si = 0, sj = 0; si < indentMult; si ++ )
 					{
-						var startC = line[ si ];
+						var startC = line[ sj ];
 						if( startC == " " )
 						{
-							for( ; sj < tabwidth; sj ++ )
+							for( var swidth = tabwidth + ( sj ++ ); sj < swidth; sj ++ )
 							{
-								if( !~"\t ".indexOf( line[ si + sj ] ) ) break;
+								if( !~"\t ".indexOf( line[ sj ] ) ) break;
 							}
 						}
 						else if( startC != "\t" ) break;
 					}
 
-					indentedLine = line.substring( si + sj - 1 );
+					indentedLine = line.substring( sj );
 				}
 
 				feeder.content += indentedLine;
@@ -267,7 +328,14 @@
 
 		cur.rec.record( stack );
 
-		this.__msg = Mesg( "LINES_SHIFTED", nline, dir < 0 ? "<" : ">", 1 );
+		if( nline )
+		{
+			this.__msg = Mesg( "LINES_SHIFTED", nline, dir < 0 ? "<" : ">", indentMult );
+		}
+		else
+		{
+			this.__msg = Mesg( "NO_SHIFT", dir < 0 ? "<" : ">" );
+		}
 
 		return Triggered;
 	};
diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js
index 1d4071d..5e0cbea 100644
--- a/botanjs/src/Components/Vim/Actions/VISUAL.js
+++ b/botanjs/src/Components/Vim/Actions/VISUAL.js
@@ -10,6 +10,8 @@
 	var YANK = ns[ NS_INVOKE ]( "YANK" );
 	/** @type {Components.Vim.IAction} */
 	var DELETE = ns[ NS_INVOKE ]( "DELETE" );
+	/** @type {Components.Vim.IAction} */
+	var SHIFT_LINES = ns[ NS_INVOKE ]( "SHIFT_LINES" );
 
 	var MODE_NULL = -1;
 	var MODE_VISUAL = 0;
@@ -129,6 +131,10 @@
 				this.__msg = Mesg( "VISLINE" );
 			}
 		}
+		else if( e.kMap( "<" ) || e.kMap( ">" ) )
+		{
+			Action = new SHIFT_LINES( cur, e );
+		}
 		else if( e.kMap( "v" ) )
 		{
 			if( this.__mode == MODE_VISUAL ) return true;
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index c34a4d9..1173343 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -300,8 +300,9 @@
 		var ccur = this.__ccur;
 
 		var x = ccur.X;
+		var y = ccur.Y;
 		ccur.moveX( a, b, c || ccur.pSpace );
-		if( ccur.X == x )
+		if( ccur.X == x && ccur.Y == y )
 		{
 			beep();
 			return false;
@@ -559,15 +560,32 @@
 				this.__composite( e, curlyBracket, SHIFT + S_BRACKET_R );
 				break;
 
-			case G: // Go to top
+			case G:
+
 				this.__cMovement = true;
-				this.__composite( e, function(){
+
+				// Go to top
+				this.__composite( e, function() {
 					ccur.moveY( -Number.MAX_VALUE );
 					ccur.moveX( -Number.MAX_VALUE, true );
 				}, G );
-				this.__composite( e, function(){
+
+				// Print Hex
+				this.__composite( e, function() {
 					ccur.openRunAction( "PRINT_HEX", e );
 				}, _8 );
+
+				// to lowercase
+				this.__composite( e, function( e2 ) {
+					if( ccur.action ) { beep(); return; }
+					// TODO
+				}, U );
+
+				// to uppercase
+				this.__composite( e, function( e2 ) {
+					if( ccur.action ) { beep(); return; }
+					// TODO
+				}, SHIFT + U );
 				break;
 
 			case SHIFT + N: // Next Search
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index dedf3f4..bfa1b4b 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -26,6 +26,8 @@ VIMRE_VERSION = "1.0.0b";
 		, "LINES_YANKED": "%1 line(s) yanked"
 		, "LINES_SHIFTED": "%1 line(s) %2ed %3 time(s)"
 
+		, "NO_SHIFT": "No line to %1"
+
 		, "SEARCH_HIT_BOTTOM": "search hit BOTTOM, continuing at TOP"
 		, "SEARCH_HIT_TOP": "search hit TOP, continuing at BOTTOM"
 		, "REPLACE": "%1 substitution(s) on %2 line(s)"