penguin/AstroJS

Javascript framework for my blog

commit c7249c071c9b3aa6787b930e0d9c4ce3e5dd42b1

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-04-02T06:25:25Z
subjectSearch Ex Draft
commit c7249c071c9b3aa6787b930e0d9c4ce3e5dd42b1
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-04-02T06:25:25Z

    Search Ex Draft
---
 botanjs/src/Components/Vim/Actions/PUT.js       |   2 -
 botanjs/src/Components/Vim/Controls.js          | 123 ++++++++++++++++---
 botanjs/src/Components/Vim/Cursor.js            |   6 +-
 botanjs/src/Components/Vim/Ex/Search.js         | 150 ++++++++++++++++++++++++
 botanjs/src/Components/Vim/StatusBar.js         |   5 +
 botanjs/src/Components/Vim/VimArea.js           |   5 +-
 botanjs/src/externs/Components.Vim.StatusBar.js |   2 +
 7 files changed, 268 insertions(+), 25 deletions(-)

diff --git a/botanjs/src/Components/Vim/Actions/PUT.js b/botanjs/src/Components/Vim/Actions/PUT.js
index 2dbb263..e58c9f9 100644
--- a/botanjs/src/Components/Vim/Actions/PUT.js
+++ b/botanjs/src/Components/Vim/Actions/PUT.js
@@ -1,8 +1,6 @@
 (function(){
 	var ns = __namespace( "Components.Vim.Actions" );
 
-	var Mesg = __import( "Components.Vim.Message" );
-
 	/** @type {Components.Vim.State.Stator} */
 	var Stator                                 = __import( "Components.Vim.State.Stator" );
 	/** @type {Components.Vim.State.Stack} */
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 587cda3..e129357 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -3,6 +3,10 @@
 
 	/** @type {System.Debug} */
 	var debug = __import( "System.Debug" );
+
+	/** @type {Components.Vim.Ex.Search} */
+	var ExSearch = __import( "Components.Vim.Ex.Search" );
+
 	var beep = ns[ NS_INVOKE ]( "Beep" );
 
 	var SHIFT = 1 << 9;
@@ -14,8 +18,12 @@
 	var KEY_ALT = 18;
 
 	var BACKSPACE = 8;
+	var TAB = 9;
+	var ENTER = 13;
 	var DELETE = 46;
 
+	var UP = 38; var DOWN = 40; var LEFT = 37; var RIGHT = 39;
+
 	var _0 = 48; var _1 = 49; var _2 = 50; var _3 = 51; var _4 = 52;
 	var _5 = 53; var _6 = 54; var _7 = 55; var _8 = 56; var _9 = 57;
 
@@ -70,6 +78,13 @@
 		{
 			case "BS": kCode = Mod + BACKSPACE; break;
 			case "Del": kCode = Mod + DELETE; break;
+			case "Enter": kCode = Mod + ENTER; break;
+			case "Tab": kCode = Mod + TAB; break;
+
+			case "Up": kCode = Mod + UP; break;
+			case "Down": kCode = Mod + DOWN; break;
+			case "Left": kCode = Mod + LEFT; break;
+			case "Right": kCode = Mod + RIGHT; break;
 
 			case "A": Mod = SHIFT; case "a": kCode = Mod + A; break;
 			case "B": Mod = SHIFT; case "b": kCode = Mod + B; break;
@@ -127,6 +142,10 @@
 		this.__sfeeder = vimArea.statusFeeder;
 
 		this.__ccur = this.__cfeeder.cursor;
+
+		// Dived composite command handler
+		// Has full control of the key input, except Esc
+		this.__divedCCmd = null;
 	};
 
 	Controls.prototype.__composite = function( e, handler )
@@ -183,6 +202,19 @@
 			case I: // Insert
 				ccur.openAction( "INSERT" );
 				break;
+
+			case SHIFT + O: // new line before insert
+				ccur.lineStart();
+				ccur.openAction( "INSERT" );
+				ccur.action.handler( new InputEvent( e.sender, "Enter" ) );
+				ccur.moveY( -1 );
+				break;
+			case O: // new line insert
+				ccur.lineEnd( true );
+				ccur.openAction( "INSERT" );
+				ccur.action.handler( new InputEvent( e.sender, "Enter" ) );
+				break;
+
 			case U: // Undo
 				ccur.openRunAction( "UNDO", e );
 				break;
@@ -205,9 +237,15 @@
 				ccur.openRunAction( "PUT", e );
 				break;
 
-			case X: // Del
-				break;
 			case SHIFT + X: // Delete before
+				if( !this.__cMoveX( -1 ) ) break;
+			case X: // Del
+				if( ccur.getLine().content == "" )
+				{
+					beep();
+					break;
+				}
+				ccur.openRunAction( "DELETE", e, ccur.aPos );
 				break;
 			case SHIFT + U: // Undo previous changes in oneline
 				break;
@@ -240,7 +278,12 @@
 
 		var x = ccur.X;
 		ccur.moveX( a, b, c || ccur.pSpace );
-		if( ccur.X == x ) beep();
+		if( ccur.X == x )
+		{
+			beep();
+			return false;
+		}
+		return true;
 	};
 
 	Controls.prototype.__cMoveY = function( a )
@@ -252,16 +295,18 @@
 		ccur.moveY( a );
 		if( y == ( ccur.Y + cfeeder.panY ) )
 		{
-			if( 0 < a && !cfeeder.EOF ) return;
+			if( 0 < a && !cfeeder.EOF ) return true;
 			beep();
 		}
+
+		return false;
 	};
 
 	Controls.prototype.__cursorCommand = function( e )
 	{
 		var kCode = e.keyCode;
 
-		if( this.__cMovement && this.__composite )
+		if( this.__cMovement )
 		{
 			if( !e.ModKeys )
 			{
@@ -396,9 +441,11 @@
 				}, _8 );
 				break;
 
-			case SLASH: // "/" Seach movement
 			case SLASH: // "/" Seach movement
 				this.__cMovement = true;
+
+				this.__divedCCmd = new ExSearch( ccur );
+				this.__divedCCmd.handler( e );
 				break;
 			default:
 				cursorHandled = false;
@@ -420,12 +467,39 @@
 		) return;
 
 		// Clear composite command
-		if( e.Escape && this.__compositeReg )
+		if( e.Escape )
 		{
-			this.__compositeReg = null;
+			var b = false;
 			this.__cMovement = false;
-			beep();
-			return;
+
+			if( this.__compositeReg )
+			{
+				b = true;
+				this.__compositeReg = null;
+			}
+			else if( this.__divedCCmd )
+			{
+				b = true;
+				this.__divedCCmd.dispose();
+				this.__divedCCmd = null;
+			}
+
+			if( b )
+			{
+				beep();
+				return;
+			}
+		}
+
+		if( this.__divedCCmd )
+		{
+			if( this.__divedCCmd.handler( e ) )
+			{
+				this.__divedCCmd.dispose();
+				this.__cMovement = false;
+				this.__divedCCmd = null;
+			}
+			else return;
 		}
 
 		var cfeeder = this.__cfeeder;
@@ -470,19 +544,30 @@
 
 	var InputEvent = function( sender, e )
 	{
-		this.__e = e;
 		this.__target = sender;
 
-		var c = this.__e.keyCode;
+		if( typeof( e ) == "string" )
+		{
+			this.__key = e;
+			this.__modKeys = 0;
+			this.__kCode = Map( e );
+			this.__escape = this.__kCode == ESC;
+		}
+		else
+		{
+			this.__e = e;
 
-		this.__escape = c == ESC || ( e.ctrlKey && c == C );
-		this.__kCode = c
-			+ ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
-			+ ( e.ctrlKey ? CTRL : 0 )
-			+ ( e.altKey ? ALT : 0 );
+			var c = this.__e.keyCode;
 
-		this.__modKeys = c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
-		this.__key = e.key;
+			this.__escape = c == ESC || ( e.ctrlKey && c == C );
+			this.__kCode = c
+				+ ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
+				+ ( e.ctrlKey ? CTRL : 0 )
+				+ ( e.altKey ? ALT : 0 );
+
+			this.__modKeys = c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
+			this.__key = e.key;
+		}
 
 		this.__range = null;
 	};
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index be80a42..bd1967d 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -396,11 +396,11 @@
 	};
 
 	// Open, Run, then close an action
-	Cursor.prototype.openRunAction = function( name, e )
+	Cursor.prototype.openRunAction = function( name, e, arg1 )
 	{
 		/** @type {Components.Vim.IAction} */
 		var action = new (Actions[ name ])( this );
-		action.handler( e );
+		action.handler( e, arg1 );
 		this.__pulseMsg = action.getMessage();
 		action.dispose();
 
@@ -497,6 +497,8 @@
 		return p;
 	} );
 
+	__readOnly( Cursor.prototype, "face", function() { return "\u2588"; } );
+
 	__readOnly( Cursor.prototype, "message", function()
 	{
 		if( this.__pulseMsg )
diff --git a/botanjs/src/Components/Vim/Ex/Search.js b/botanjs/src/Components/Vim/Ex/Search.js
new file mode 100644
index 0000000..169f5a5
--- /dev/null
+++ b/botanjs/src/Components/Vim/Ex/Search.js
@@ -0,0 +1,150 @@
+(function(){
+	var ns = __namespace( "Components.Vim.Ex" );
+
+	/** @type {System.Cycle} */
+	var Cycle                        = __import( "System.Cycle" );
+	/** @type {System.Debug} */
+	var debug                        = __import( "System.Debug" );
+	/** @type {System.utils.Perf} */
+	var Perf                         = __import( "System.utils.Perf" );
+
+	var Mesg = __import( "Components.Vim.Message" );
+
+	/** @type {Components.Vim.Cursor.IAction} */
+	var Search = function( Cursor )
+	{
+		var _self = this;
+
+		/** @type {Components.Vim.Cursor} */
+		this.__cursor = Cursor;
+
+		this.__statusBar = Cursor.Vim.statusBar;
+
+		this.__command = [];
+		this.__blinkId = "ExSearchBlinkCycle" + Perf.uuid;
+		this.__curPos = 0;
+
+		this.__disp = function()
+		{
+		};
+
+        var feeder = Cursor.feeder;
+
+		var __blink = false;
+		var __holdBlink = false;
+		this.__blink = function()
+		{
+			__blink = true;
+			__holdBlink = true
+		};
+
+		Cycle.perma( this.__blinkId, function()
+		{
+			if( __holdBlink ) __holdBlink = false;
+			else __blink = !__blink;
+
+			feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+		}, 600 );
+
+		this.__doBlink = function()
+		{
+			var c = "";
+			var comm = _self.__command;
+			var pos = _self.__curPos;
+			var cLen = comm.length;
+			var faced = true;
+
+			for( var i = 0; i < cLen; i ++ )
+			{
+				var v = comm[i];
+				if( __blink && i == pos )
+				{
+					face = true;
+					v = Cursor.face + v.substr( 1 );
+				}
+
+				c+= v;
+			}
+
+			if( __blink && cLen <= pos )
+			{
+				c += Cursor.face;
+			}
+
+			return c;
+		};
+
+		this.__statusBar.override = this.__doBlink;
+	};
+
+	Search.prototype.dispose = function()
+	{
+		this.__statusBar.override = null;
+
+		Cycle.permaRemove( this.__blinkId );
+		var feeder = this.__cursor.feeder;
+		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+	};
+
+	Search.prototype.handler = function( e )
+	{
+		e.preventDefault();
+
+		if( e.ModKeys ) return;
+
+		this.__blink();
+
+		var InputKey = null;
+
+		if( e.kMap( "Tab" ) )
+		{
+			InputKey = "^I";
+		}
+		else if( e.kMap( "C-v" ) )
+		{
+			this.__direct = true;
+		}
+		else if( e.kMap( "BS" ) )
+		{
+			this.__command.splice( --this.__curPos, 1 );
+			if( this.__command.length == 0 ) return true;
+		}
+		else if( e.kMap( "Del" ) )
+		{
+			this.__command.splice( this.__curPos, 1 );
+		}
+		else if( e.kMap( "Enter" ) )
+		{
+			return true;
+		}
+		else if( e.kMap( "Up" ) ) // History navigations
+		{
+		}
+		else if( e.kMap( "Down" ) )
+		{
+		}
+		else if( e.kMap( "Left" ) )
+		{
+			if( 0 < this.__curPos ) this.__curPos --;
+		}
+		else if( e.kMap( "Right" ) )
+		{
+			if( this.__curPos < this.__command.length )
+				this.__curPos ++;
+		}
+		else
+		{
+			InputKey = e.key;
+		}
+
+		if( InputKey != null )
+		{
+			this.__command.splice( this.__curPos ++, 0, InputKey );
+		}
+
+		var feeder = this.__cursor.feeder;
+		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+	}
+
+	ns[ NS_EXPORT ]( EX_CLASS, "Search", Search );
+})();
diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js
index 1a57d5c..81af357 100644
--- a/botanjs/src/Components/Vim/StatusBar.js
+++ b/botanjs/src/Components/Vim/StatusBar.js
@@ -10,6 +10,7 @@
 	{
 		this.cols = cols;
 		this.statStamp = {};
+		this.override = null;
 	};
 
 	StatusBar.prototype.stamp = function( pos, func )
@@ -17,8 +18,12 @@
 		this.statStamp[ pos ] = func;
 	};
 
+	StatusBar.prototype.override;
+
 	__readOnly( StatusBar.prototype, "statusText", function()
 	{
+		if( this.override ) return this.override();
+
 		var display = "";
 		var l = this.cols;
 
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 95b02c6..c5480ec 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -123,9 +123,10 @@
 		{
 			sfeeder.init( statusBar.statusText );
 
+			var sLine = sfeeder.linesOccupied;
 			element.value =
-				cfeeder.render( 0, r - sfeeder.linesOccupied )
-				+ "\n" + sfeeder.render();
+				cfeeder.render( 0, r - sLine )
+				+ "\n" + sfeeder.render( 0, sLine < r ? sLine : r );
 
 			_self.__blink = false;
 			_self.select( cfeeder.cursor.position );
diff --git a/botanjs/src/externs/Components.Vim.StatusBar.js b/botanjs/src/externs/Components.Vim.StatusBar.js
index 356c980..8e43a79 100644
--- a/botanjs/src/externs/Components.Vim.StatusBar.js
+++ b/botanjs/src/externs/Components.Vim.StatusBar.js
@@ -3,5 +3,7 @@ Components.Vim.StatusBar = function(){};
 
 /** @type Function */
 Components.Vim.StatusBar.stamp;
+/** @type Function */
+Components.Vim.StatusBar.override;
 /** @type String */
 Components.Vim.StatusBar.statusText;