penguin/AstroJS

Javascript framework for my blog

commit 75662e6d0426339b1eff5d1499ca163761840b40

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-22T09:35:49Z
subjectSome placeholder commands in VISUAL
commit 75662e6d0426339b1eff5d1499ca163761840b40
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-22T09:35:49Z

    Some placeholder commands in VISUAL
---
 botanjs/src/Components/Vim/Actions/DELETE.js       | 32 ++++++++
 botanjs/src/Components/Vim/Actions/VISUAL.js       | 44 ++++++++--
 botanjs/src/Components/Vim/Actions/YANK.js         | 32 ++++++++
 botanjs/src/Components/Vim/Controls.js             | 96 +++++++++++++++++++++-
 botanjs/src/Components/Vim/Cursor.js               |  8 +-
 botanjs/src/Components/Vim/State/Registers.js      | 50 +++++++++++
 botanjs/src/Components/Vim/VimArea.js              | 34 +++++---
 botanjs/src/externs/Components.Vim.Controls.js     |  7 ++
 botanjs/src/externs/Components.Vim.Cursor.js       |  2 +
 .../src/externs/Components.Vim.State.Recorder.js   |  6 +-
 .../src/externs/Components.Vim.State.Registers.js  |  9 ++
 botanjs/src/externs/Components.Vim.VimArea.js      |  2 +
 12 files changed, 296 insertions(+), 26 deletions(-)

diff --git a/botanjs/src/Components/Vim/Actions/DELETE.js b/botanjs/src/Components/Vim/Actions/DELETE.js
new file mode 100644
index 0000000..113a417
--- /dev/null
+++ b/botanjs/src/Components/Vim/Actions/DELETE.js
@@ -0,0 +1,32 @@
+(function(){
+	var ns = __namespace( "Components.Vim.Actions" );
+
+	var Mesg = __import( "Components.Vim.Message" );
+
+	/** @type {Components.Vim.Cursor.IAction} */
+	var DELETE = function( Cursor )
+	{
+		/** @type {Components.Vim.Cursor} */
+		this.__cursor = Cursor;
+	};
+
+	DELETE.prototype.allowMovement = true;
+
+	DELETE.prototype.dispose = function()
+	{
+
+	};
+
+	DELETE.prototype.handler = function( e )
+	{
+		e.preventDefault();
+
+	};
+
+	DELETE.prototype.getMessage = function()
+	{
+		return "<TODO> DELETE COMMAND";
+	};
+
+	ns[ NS_EXPORT ]( EX_CLASS, "DELETE", DELETE );
+})();
diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js
index 752eaec..dad2fbb 100644
--- a/botanjs/src/Components/Vim/Actions/VISUAL.js
+++ b/botanjs/src/Components/Vim/Actions/VISUAL.js
@@ -1,12 +1,17 @@
 (function(){
 	var ns = __namespace( "Components.Vim.Actions" );
 
-	/** @type {Components.Vim.State.Stack} */
-	var Stack                                 = __import( "Components.Vim.State.Stack" );
 	/** @type {System.Debug} */
-	var debug                                 = __import( "System.Debug" );
+	var debug = __import( "System.Debug" );
 
 	var Mesg = __import( "Components.Vim.Message" );
+	/** @type {Components.Vim.Controls} */
+	var Controls = __import( "Components.Vim.Controls" );
+
+	/** @type {Components.Vim.Cursor.IAction} */
+	var YANK = ns[ NS_INVOKE ]( "YANK" );
+	/** @type {Components.Vim.Cursor.IAction} */
+	var DELETE = ns[ NS_INVOKE ]( "DELETE" );
 
 	/** @type {Components.Vim.Cursor.IAction} */
 	var VISUAL = function( Cursor )
@@ -16,6 +21,8 @@
 		this.__startaP = Cursor.aPos;
 		this.__start = Cursor.PStart;
 		this.__selStart = Cursor.PStart;
+		this.__msg = Mesg( "VISUAL" );
+		this.__leaveMesg = "";
 
 		Cursor.blink = false;
 	};
@@ -24,17 +31,38 @@
 
 	VISUAL.prototype.dispose = function()
 	{
+		this.__msg = this.__leaveMesg;
 		this.__cursor.blink = true;
 		this.__cursor.PStart = this.__selStart;
 		this.__cursor.PEnd = this.__selStart + 1;
 	};
 
-
-	VISUAL.prototype.handler = function( e )
+	VISUAL.prototype.handler = function( e, done )
 	{
 		e.preventDefault();
 
-		if( [ 16, 17, 18 ].indexOf( e.keyCode ) != -1 ) return;
+		if( Controls.ModKeys( e ) ) return;
+
+		var Action = null;
+		switch( true )
+		{
+			case Controls.KMap( e, "y" ):
+				Action = new YANK( this.__cursor );
+				break;
+			case Controls.KMap( e, "d" ):
+				Action = new DELETE( this.__cursor );
+				break;
+		}
+
+		if( Action )
+		{
+			Action.handler( e );
+			this.__leaveMesg = Action.getMessage();
+			Action.dispose();
+
+			return true;
+		}
+
 		var cur = this.__cursor;
 		var prevPos = this.__start;
 		var newPos = cur.PStart;
@@ -58,9 +86,7 @@
 
 	VISUAL.prototype.getMessage = function()
 	{
-		var msg = Mesg( "VISUAL" );
-
-		return msg;
+		return this.__msg;
 	};
 
 	ns[ NS_EXPORT ]( EX_CLASS, "VISUAL", VISUAL );
diff --git a/botanjs/src/Components/Vim/Actions/YANK.js b/botanjs/src/Components/Vim/Actions/YANK.js
new file mode 100644
index 0000000..ba987d7
--- /dev/null
+++ b/botanjs/src/Components/Vim/Actions/YANK.js
@@ -0,0 +1,32 @@
+(function(){
+	var ns = __namespace( "Components.Vim.Actions" );
+
+	var Mesg = __import( "Components.Vim.Message" );
+
+	/** @type {Components.Vim.Cursor.IAction} */
+	var YANK = function( Cursor )
+	{
+		/** @type {Components.Vim.Cursor} */
+		this.__cursor = Cursor;
+	};
+
+	YANK.prototype.allowMovement = true;
+
+	YANK.prototype.dispose = function()
+	{
+
+	};
+
+	YANK.prototype.handler = function( e )
+	{
+		e.preventDefault();
+
+	};
+
+	YANK.prototype.getMessage = function()
+	{
+		return "<TODO> YANK COMMAND";
+	};
+
+	ns[ NS_EXPORT ]( EX_CLASS, "YANK", YANK );
+})();
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index f55181b..918cc41 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -1,6 +1,7 @@
 (function(){
 	var ns = __namespace( "Components.Vim" );
 
+	/** @type {System.Debug} */
 	var debug = __import( "System.Debug" );
 	var beep = ns[ NS_INVOKE ]( "Beep" );
 
@@ -29,6 +30,81 @@
 	var F6 = 117; var F7 = 118; var F8 = 119; var F9 = 120; var F10 = 121;
 	var F11 = 122; var F12 = 123;
 
+	var __maps = {};
+	var Map = function( str )
+	{
+		if( __maps[ str ] ) return __maps[ str ];
+
+		// C-Left, A-Up ...
+		var Code = str.split( "-" );
+		var sCode = Code[0];
+
+		var Mod = 0;
+		if( Code.length == 2 )
+		{
+			var m = true;
+			switch( Code[0] )
+			{
+				case "C": Mod = CTRL; break;
+				case "A": Mod = ALT; break;
+				case "S": Mod = SHIFT; break;
+				default:
+					m = false;
+			}
+
+			if( m )
+			{
+				sCode = Code[1];
+			}
+		}
+
+		var kCode;
+		switch( sCode )
+		{
+			case "A": Mod = SHIFT; case "a": kCode = Mod + A; break;
+			case "B": Mod = SHIFT; case "b": kCode = Mod + B; break;
+			case "C": Mod = SHIFT; case "c": kCode = Mod + C; break;
+			case "D": Mod = SHIFT; case "d": kCode = Mod + D; break;
+			case "E": Mod = SHIFT; case "e": kCode = Mod + E; break;
+			case "F": Mod = SHIFT; case "f": kCode = Mod + F; break;
+			case "G": Mod = SHIFT; case "g": kCode = Mod + G; break;
+			case "H": Mod = SHIFT; case "h": kCode = Mod + H; break;
+			case "I": Mod = SHIFT; case "i": kCode = Mod + I; break;
+			case "J": Mod = SHIFT; case "j": kCode = Mod + J; break;
+			case "K": Mod = SHIFT; case "k": kCode = Mod + K; break;
+			case "L": Mod = SHIFT; case "l": kCode = Mod + L; break;
+			case "M": Mod = SHIFT; case "m": kCode = Mod + M; break;
+			case "N": Mod = SHIFT; case "n": kCode = Mod + N; break;
+			case "O": Mod = SHIFT; case "o": kCode = Mod + O; break;
+			case "P": Mod = SHIFT; case "p": kCode = Mod + P; break;
+			case "Q": Mod = SHIFT; case "q": kCode = Mod + Q; break;
+			case "R": Mod = SHIFT; case "r": kCode = Mod + R; break;
+			case "S": Mod = SHIFT; case "s": kCode = Mod + S; break;
+			case "T": Mod = SHIFT; case "t": kCode = Mod + T; break;
+			case "U": Mod = SHIFT; case "u": kCode = Mod + U; break;
+			case "V": Mod = SHIFT; case "v": kCode = Mod + V; break;
+			case "W": Mod = SHIFT; case "w": kCode = Mod + W; break;
+			case "X": Mod = SHIFT; case "x": kCode = Mod + X; break;
+			case "Y": Mod = SHIFT; case "y": kCode = Mod + Y; break;
+			case "Z": Mod = SHIFT; case "z": kCode = Mod + Z; break;
+
+			case "!": Mod = SHIFT; case "1": kCode = Mod + _1; break;
+			case "@": Mod = SHIFT; case "2": kCode = Mod + _2; break;
+			case "#": Mod = SHIFT; case "3": kCode = Mod + _3; break;
+			case "$": Mod = SHIFT; case "4": kCode = Mod + _4; break;
+			case "%": Mod = SHIFT; case "5": kCode = Mod + _5; break;
+			case "^": Mod = SHIFT; case "6": kCode = Mod + _6; break;
+			case "&": Mod = SHIFT; case "7": kCode = Mod + _7; break;
+			case "*": Mod = SHIFT; case "8": kCode = Mod + _8; break;
+			case "(": Mod = SHIFT; case "9": kCode = Mod + _9; break;
+			case ")": Mod = SHIFT; case "0": kCode = Mod + _0; break;
+			default:
+				throw new Error( "No such keys: " + str );
+		}
+
+		return __maps[ str ] = kCode;
+	};
+
 	var Controls = function( vimArea )
 	{
 		/** @type {Components.Vim.VimArea} */
@@ -249,7 +325,10 @@
 				if( ccur.action.allowMovement )
 					this.__cursorCommand( e, kCode );
 
-				ccur.action.handler( e );
+				if( ccur.action.handler( e ) )
+				{
+					ccur.closeAction();
+				}
 			}
 			return;
 		}
@@ -260,5 +339,20 @@
 		if( this.__actionCommand( e, kCode ) ) return;
 	};
 
+	__static_method( Controls, "ModKeys", function( e )
+	{
+		var c = e.keyCode;
+		return c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
+	} );
+
+	__static_method( Controls, "KMap", function( e, map )
+	{
+		var kCode = e.keyCode
+			+ ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
+			+ ( e.ctrlKey ? CTRL : 0 );
+
+		return kCode == Map( map );
+	} );
+
 	ns[ NS_EXPORT ]( EX_CLASS, "Controls", Controls );
 })();
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index 51377a5..0481f30 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -82,6 +82,9 @@
 		this.blink = true;
 	};
 
+	// Set by VimArea
+	Cursor.prototype.Vim;
+
 	// Can only be 1, -1
 	// 0 will be treated as undefined
 	Cursor.prototype.moveX = function( d, penentrate, phantomSpace )
@@ -259,6 +262,8 @@
 		this.updatePosition();
 	};
 
+	// Open an action handler
+	// i.e. YANK, VISUAL, INSERT, UNDO, etc.
 	Cursor.prototype.openAction = function( name )
 	{
 		if( this.action ) this.action.dispose();
@@ -272,12 +277,13 @@
 	{
 		if( !this.action ) return;
 		this.action.dispose();
+		this.__pulseMsg = this.action.getMessage();
 		this.action = null;
-		this.__pulseMsg = null;
 
 		this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
 	};
 
+	// Open, Run, then close an action
 	Cursor.prototype.openRunAction = function( name, e )
 	{
 		/** @type {Components.Vim.IAction} */
diff --git a/botanjs/src/Components/Vim/State/Registers.js b/botanjs/src/Components/Vim/State/Registers.js
new file mode 100644
index 0000000..220fe70
--- /dev/null
+++ b/botanjs/src/Components/Vim/State/Registers.js
@@ -0,0 +1,50 @@
+(function(){
+/*  From Vim, :help registers
+	There are ten types of registers:
+	1. The unnamed register ""
+	2. 10 numbered registers "0 to "9
+	3. The small delete register "-
+	4. 26 named registers "a to "z or "A to "Z
+	5. three read-only registers ":, "., "%
+	6. alternate buffer register "#
+	7. the expression register "=
+	8. The selection and drop registers "*, "+ and "~ 
+	9. The black hole register "_
+	10. Last search pattern register "/
+	i.e. 0123456789-abcdefghijklmnopqrstuvwxyz:.%$=*+~_/
+*/
+	var ns = __namespace( "Components.Vim.State" );
+
+	var Registers = function()
+	{
+		this.__registers = {};
+	};
+
+	Registers.prototype.unnamed = function( str )
+	{
+		this.__registers[ "\"" ] = str;
+	};
+
+	Registers.prototype.yank = function( str )
+	{
+		this.unnamed( str );
+		this.__registers[ 0 ] = str;
+	};
+
+	Registers.prototype.change = function( str )
+	{
+		this.unnamed( str );
+		var r = this.__registers;
+		for( var i = 9; 1 < i; i -- )
+		{
+			if( r[ i - 1 ] != undefined )
+			{
+				r[ i ] = r[ i - 1 ];
+			}
+		}
+
+		r[ 1 ] = str;
+	};
+
+	ns[ NS_EXPORT ]( EX_CLASS, "Registers", Registers );
+})();
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 8ecb7a9..d02bdf4 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -10,6 +10,9 @@
 	/** @type {System.Debug} */
 	var debug                                   = __import( "System.Debug" );
 
+	/** @type {Components.Vim.State.Registers} */
+	var Registers                               = __import( "Components.Vim.State.Registers" );
+
 	/** @type {Components.Vim.LineFeeder} */
 	var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
 	/** @type {Components.Vim.StatusBar} */
@@ -18,6 +21,8 @@
 	var VimControls = ns[ NS_INVOKE ]( "Controls" );
 	var mesg = ns[ NS_INVOKE ]( "Message" );
 
+	var Insts = [];
+
 	var KeyHandler = function( sender, handler )
 	{
 		return function( e )
@@ -58,6 +63,9 @@
 
 		// Init
 		this.VisualizeVimFrame( element.value );
+
+		// Push this instance
+		Insts.push( this );
 	};
 
 	VimArea.prototype.select = function( sel )
@@ -86,6 +94,7 @@
 		// Content feeder
 		var cfeeder = new LineFeeder( cRange, c );
 
+		// Feed the contents to content feeder
 		// This "\n" fixes the last line "\n" not displaying
 		// it will be trimmed after saving
 		cfeeder.init( content + "\n" );
@@ -94,19 +103,15 @@
 		sfeeder = new LineFeeder( r, c );
 		sfeeder.setRender( false );
 
-		// XXX: Placeholder
-		var statusBar = new StatusBar( c );
-		statusBar.stamp( -18, function(){
-			return cfeeder.lineStat;
-		});
-
-		statusBar.stamp( -3, function(){
-			return mesg( cfeeder.docPos );
-		} );
+		// Set the Vim instance
+		cfeeder.cursor.Vim = this;
+		sfeeder.cursor.Vim = this;
 
-		statusBar.stamp( 0, function(){
-			return cfeeder.cursor.message;
-		} );
+		// Set the stamps
+		var statusBar = new StatusBar( c );
+		statusBar.stamp( -18, function(){ return cfeeder.lineStat; } );
+		statusBar.stamp( -3, function(){ return mesg( cfeeder.docPos ); } );
+		statusBar.stamp( 0, function(){ return cfeeder.cursor.message; } );
 
 		sfeeder.init( statusBar.statusText );
 
@@ -128,6 +133,7 @@
 		this.contentFeeder = cfeeder;
 		this.statusFeeder = sfeeder;
 		this.statusBar = statusBar;
+		this.registers = new Registers();
 
 		this.__cursor = cfeeder.cursor;
 
@@ -148,6 +154,10 @@
 		);
 	};
 
+	__readOnly( VimArea, "Instances", function() {
+		return Insts.slice();
+	} );
+
 	__readOnly( VimArea.prototype, "content", function() {
 		return this.contentFeeder.content.slice( 0, -1 );
 	} );
diff --git a/botanjs/src/externs/Components.Vim.Controls.js b/botanjs/src/externs/Components.Vim.Controls.js
new file mode 100644
index 0000000..6fec2e7
--- /dev/null
+++ b/botanjs/src/externs/Components.Vim.Controls.js
@@ -0,0 +1,7 @@
+/** @constructor */
+Components.Vim.Controls = function(){};
+
+/** @type Function */
+Components.Vim.Controls.ModKeys;
+/** @type Function */
+Components.Vim.Controls.KMap;
diff --git a/botanjs/src/externs/Components.Vim.Cursor.js b/botanjs/src/externs/Components.Vim.Cursor.js
index 0873383..76fef9d 100644
--- a/botanjs/src/externs/Components.Vim.Cursor.js
+++ b/botanjs/src/externs/Components.Vim.Cursor.js
@@ -1,6 +1,8 @@
 /** @constructor */
 Components.Vim.Cursor = function(){};
 
+/** @type {Components.Vim.VimArea} */
+Components.Vim.Cursor.Vim;
 /** @type {Components.Vim.LineFeeder} */
 Components.Vim.Cursor.feeder;
 /** @type {Components.Vim.IAction} */
diff --git a/botanjs/src/externs/Components.Vim.State.Recorder.js b/botanjs/src/externs/Components.Vim.State.Recorder.js
index 0303938..b39cbf9 100644
--- a/botanjs/src/externs/Components.Vim.State.Recorder.js
+++ b/botanjs/src/externs/Components.Vim.State.Recorder.js
@@ -2,8 +2,8 @@
 Components.Vim.State.Recorder = function(){};
 
 /** @type Function */
-Components.Vim.State.undo;
+Components.Vim.State.Recorder.undo;
 /** @type Function */
-Components.Vim.State.redo;
+Components.Vim.State.Recorder.redo;
 /** @type Function */
-Components.Vim.State.record;
+Components.Vim.State.Recorder.record;
diff --git a/botanjs/src/externs/Components.Vim.State.Registers.js b/botanjs/src/externs/Components.Vim.State.Registers.js
new file mode 100644
index 0000000..75b9c13
--- /dev/null
+++ b/botanjs/src/externs/Components.Vim.State.Registers.js
@@ -0,0 +1,9 @@
+/** @constructor */
+Components.Vim.State.Registers = function(){};
+
+/** @type Function */
+Components.Vim.State.Registers.change;
+/** @type Function */
+Components.Vim.State.Registers.yank;
+/** @type Function */
+Components.Vim.State.Registers.unnamed;
diff --git a/botanjs/src/externs/Components.Vim.VimArea.js b/botanjs/src/externs/Components.Vim.VimArea.js
index e71c020..982acda 100644
--- a/botanjs/src/externs/Components.Vim.VimArea.js
+++ b/botanjs/src/externs/Components.Vim.VimArea.js
@@ -12,3 +12,5 @@ Components.Vim.VimArea.statusBar;
 Components.Vim.VimArea.rows;
 /** @type {Number} */
 Components.Vim.VimArea.cols;
+/** @type {Array} */
+Components.Vim.VimArea.Instances;