penguin/AstroJS

Javascript framework for my blog

commit acb5d72d891ae0eaedb042331df99cd11e07907e

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-17T19:35:45Z
subjectAdded a beep sound
commit acb5d72d891ae0eaedb042331df99cd11e07907e
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-17T19:35:45Z

    Added a beep sound
---
 botanjs/src/Components/Vim/Actions/INSERT.js |  37 ++----
 botanjs/src/Components/Vim/Controls.js       | 104 +++++++++++++---
 botanjs/src/Components/Vim/Cursor.js         |  27 +++++
 botanjs/src/Components/Vim/VimArea.js        |   7 +-
 botanjs/src/Components/Vim/_this.js          | 172 +++++++++++++++++++++++++++
 botanjs/src/externs/Components.Vim.Cursor.js |   2 +
 6 files changed, 303 insertions(+), 46 deletions(-)

diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js
index 7523173..0628330 100644
--- a/botanjs/src/Components/Vim/Actions/INSERT.js
+++ b/botanjs/src/Components/Vim/Actions/INSERT.js
@@ -21,38 +21,14 @@
 		}
 	};
 
-	/* @param {Components.Vim.LineFeeder} */
-	var ContentPosition = function( f )
-	{
-		var line = f.cursor.getLine();
-		var n = line.lineNum;
-
-		var p = 0;
-		if( 0 < n )
-		{
-			p = f.content.indexOf( "\n" );
-			for( i = 1; p != -1 && i < n; i ++ )
-			{
-				p = f.content.indexOf( "\n", p + 1 );
-			}
-
-			if( f.wrap )
-			{
-				// wordwrap offset
-				p ++;
-			}
-		}
-
-		p += f.cursor.aX;
-		return p;
-	};
-
 	/** @type {Components.Vim.Cursor.IAction} */
 	var INSERT = function( Cursor )
 	{
 		/** @type {Components.Vim.Cursor} */
 		this.__cursor = Cursor;
 
+		this.__startX = Cursor.aPos;
+
 		// Initialize this stack
 		this.__rec( "", true );
 	};
@@ -70,6 +46,7 @@
 		var insertLength = this.__insertLength;
 		var contentUndo = this.__contentUndo;
 		var startPos = this.__startPosition;
+		var startX = this.__startX;
 
 		return function() {
 			var contentRedo = feeder.content.substr( startPos, insertLength );
@@ -105,7 +82,7 @@
 			this.__insertLength = 0;
 			this.__contentUndo = "";
 			this.__stack = new Stack();
-			this.__startPosition = ContentPosition( this.__cursor.feeder );
+			this.__startPosition = this.__cursor.aPos;
 		}
 
 		if( c == "\n" )
@@ -129,7 +106,7 @@
 
 				cur.moveX( -1, true, true );
 
-				var f = ContentPosition( feeder );
+				var f = cur.aPos;
 
 				if( this.__insertLength <= 0 )
 				{
@@ -147,7 +124,7 @@
 
 				break;
 			case 46: // Delete
-				var f = ContentPosition( feeder );
+				var f = cur.aPos;
 
 				this.__contentUndo += feeder.content.substr( f, 1 );
 
@@ -179,7 +156,7 @@
 		var cur = this.__cursor;
 		var feeder = cur.feeder;
 
-		var f = ContentPosition( feeder );
+		var f = cur.aPos;
 
 		feeder.content =
 			feeder.content.substring( 0, f )
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 31bd7ca..dd23229 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -2,6 +2,7 @@
 	var ns = __namespace( "Components.Vim" );
 
 	var debug = __import( "System.Debug" );
+	var beep = ns[ NS_INVOKE ]( "Beep" );
 
 	var SHIFT = 1 << 9;
 	var CTRL = 1 << 10;
@@ -18,7 +19,49 @@
 	var U = 85; var V = 86; var W = 87; var X = 88; var Y = 89;
 	var Z = 90;
 
-	var Controls = function( sender, e )
+	var Controls = function()
+	{
+		this.__keyChains = [];
+	};
+
+	Controls.prototype.__comboG = function( e )
+	{
+		var keyON = this.__keyChains[ 0 ] == G;
+		if( keyON )
+		{
+			switch( e.keyCode )
+			{
+				default:
+					this.__keyChains = [];
+					return true;
+			}
+		}
+		else if( e.keyCode == G )
+		{
+			this.__keyChains[ 0 ] = G;
+			return true;
+		}
+
+		return false;
+	};
+
+	Controls.prototype.__comboT = function( e ) { return false; };
+
+	// <
+	Controls.prototype.__comboLeftShift = function( e ) { return false; };
+
+	// >
+	Controls.prototype.__comboRightShift = function( e ) { return false; };
+
+	Controls.prototype.__comboKey = function( e )
+	{
+		return this.__comboG( e )
+			|| this.__comboT( e )
+			|| this.__comboLeftShift( e )
+			|| this.__comboRightShift( e );
+	};
+
+	Controls.prototype.handler = function( sender, e )
 	{
 		// Neve capture these keys
 		if( e.altKey
@@ -28,10 +71,16 @@
 
 		// Action Mode handled by the actions themselves
 		var cfeeder = sender.contentFeeder;
+
+		// Esc OR Ctrl + c
+		var Escape = e.keyCode == 27 || ( e.ctrlKey && e.keyCode == 67 );
+
+		// Clear the keychains in combo commands
+		if( Escape ) this.__keyChains = [];
+
 		if( cfeeder.cursor.action )
 		{
-			// Esc OR Ctrl + c
-			if( e.keyCode == 27 || ( e.ctrlKey && e.keyCode == 67 ) )
+			if( Escape )
 			{
 				e.preventDefault();
 				cfeeder.cursor.closeAction();
@@ -48,39 +97,64 @@
 			+ ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
 			+ ( e.ctrlKey ? CTRL : 0 );
 
+		// Handles long commands
+
+		if( this.__comboKey( kCode ) ) return;
+
 		var cfeeder = sender.contentFeeder;
 		var sfeeder = sender.statusFeeder;
+
+		var ccur = cfeeder.cursor;
+
+		var cMoveX = function( a, b, c )
+		{
+			var x = ccur.X;
+			ccur.moveX( a, b, c );
+			if( ccur.X == x ) beep();
+		};
+
+		var cMoveY = function( a )
+		{
+			var y = ccur.Y + cfeeder.panY;
+			ccur.moveY( a );
+			if( y == ( ccur.Y + cfeeder.panY ) )
+			{
+				if( 0 < a && !cfeeder.EOF ) return;
+				beep();
+			}
+		};
+
 		switch( kCode )
 		{
 			// Cursor movements
 			case BACKSPACE: // Backspace, go back 1 char, regardless of line
-				cfeeder.cursor.moveX( -1, true );
+				cMoveX( -1, true );
 				break;
 			case H: // Left
-				cfeeder.cursor.moveX( -1 );
+				cMoveX( -1 );
 				break;
 			case L: // Right
-				cfeeder.cursor.moveX( 1 );
+				cMoveX( 1 );
 				break;
 			case K: // Up
-				cfeeder.cursor.moveY( -1 );
+				cMoveY( -1 );
 				break;
 			case J: // Down
-				cfeeder.cursor.moveY( 1 );
+				cMoveY( 1 );
 				break;
 
 			// Insert
 			case A: // Append
-				cfeeder.cursor.moveX( 1, true, true );
-				cfeeder.cursor.openAction( "INSERT" );
+				cMoveX( 1, true, true );
+				ccur.openAction( "INSERT" );
 				break;
 			case I: // Insert
 				break;
 			case U: // Undo
-				cfeeder.cursor.openRunAction( "UNDO", e );
+				ccur.openRunAction( "UNDO", e );
 				break;
 			case CTRL + R: // Redo
-				cfeeder.cursor.openRunAction( "REDO", e );
+				ccur.openRunAction( "REDO", e );
 				break;
 			case X: // Del
 				break;
@@ -104,12 +178,12 @@
 			case SHIFT + L: // Last line buffer
 				break;
 			case SHIFT + _4: // $, End
-				cfeeder.cursor.lineEnd();
+				ccur.lineEnd();
 				break;
 			case SHIFT + _5: // %, Find next item
 				break;
 			case SHIFT + _6: // ^, Start
-				cfeeder.cursor.lineStart();
+				ccur.lineStart();
 				break;
 			case SHIFT + J: // Join lines
 				break;
@@ -120,5 +194,5 @@
 
 	};
 
-	ns[ NS_EXPORT ]( EX_FUNC, "Controls", Controls );
+	ns[ NS_EXPORT ]( EX_CLASS, "Controls", Controls );
 })();
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index eb84ad1..c11d9a3 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -313,6 +313,33 @@
 		return w;
 	} );
 
+	// The absolute content position
+	__readOnly( Cursor.prototype, "aPos", function()
+	{
+		var f = this.feeder;
+		var line = this.getLine();
+		var n = line.lineNum;
+
+		var p = 0;
+		if( 0 < n )
+		{
+			p = f.content.indexOf( "\n" );
+			for( i = 1; p != -1 && i < n; i ++ )
+			{
+				p = f.content.indexOf( "\n", p + 1 );
+			}
+
+			if( f.wrap )
+			{
+				// wordwrap offset
+				p ++;
+			}
+		}
+
+		p += this.aX;
+		return p;
+	} );
+
 	__readOnly( Cursor.prototype, "message", function()
 	{
 		if( this.__pulseMsg )
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 847ca78..3f3eae5 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -53,7 +53,12 @@
 
 		var _self = this;
 
-		stage.addEventListener( "KeyDown", KeyHandler( this, VimControls ) );
+		var controls = new VimControls();
+		stage.addEventListener(
+			"KeyDown"
+			, KeyHandler( this, controls.handler.bind( controls ) )
+		);
+
 		stage.addEventListener( "Focus", function() { _self.__active = true; } );
 		stage.addEventListener( "Blur", function() { _self.__active = false; } );
 
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 4c51246..5b263b9 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -45,6 +45,178 @@
 		return GetString( errors, key, restArgs );
 	};
 
+	var bAudio = new Audio(
+		/*{{{ Audio Data */
+		"data:audio/ogg;base64,"
+		+ "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"
+		+ "wNE0QBM9QBNFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAcTQM0UQQ0UQQAAAAAAAAATRQB0VQB0TQBAAAAAAAAQBNFwDNFQDRVAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAcTQM0UQQ0UQQAAAAAAAAATRQBUTUBTzQBAAAAAAAAQBNFQDRNQFRNAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AQAAAQ4AAAEWQqEhKwKAOAEAh+NAkiBJ8DSAY1nwPHgaTBPgWBY8D5oH0wQAAAAAAAAAAABA8jR4HjwP"
+		+ "pgmQNA+eB8+DaQIAAAAAAAAAAAAgeR48D54H0wRIngfPg+fBNAEAAAAAAAAAAADwTBOmCdGEagI804Rp"
+		+ "wjRhqgAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACAAQcAgAATykChISsCgDgBAIejSBIAADiSZFkAAKBI"
+		+ "kmUBAIBlWZ4HAACSZXkeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+		+ "AAAAAAAAAAAAAAAAAAAAAAAAAIAAAIABBwCAABPKQKEhKwGAKAAAh6JYFnAcywKOY1lAkiwLYFkATQN4"
+		+ "GkAUAYAAAIACBwCAABs0JRYHKDRkJQAQBQDgcBTL0jRR5DiWpWmiyHEsS9NEkWVpmqaJIjRL00QRnud5"
+		+ "pgnP8zzThCiKomkCUTRNAQAABQ4AAAE2aEosDlBoyEoAICQAwOE4luV5oiiKpmmaqspxLMvzRFEUTVNV"
+		+ "XZfjWJbniaIomqaqui7L0jTPE0VRNE1VdV1omueJoiiapqq6LjRNFE3TNFVVVV0XmuaJpmmaqqqqrgvP"
+		+ "E0XTNE1VdV3XBaJomqapqq7rukAUTdM0VdV1XReIomiapqq6rusC0zRNVVVd15VlgGmqqqq6riwDVFVV"
+		+ "XdeVZRmgqqrquq4rywDXdV3ZlWVZBuC6rivLsiwAAODAAQAgwAg6yaiyCBtNuPAAFBqyIgCIAgAAjGFK"
+		+ "MaUMYxJCCqFhTEJIIWRSUioppQpCKiWVUkFIpaRSMkotpZZSBSGVkkqpIKRSUikFAIAdOACAHVgIhYas"
+		+ "BADyAAAIY5RizDnnJEJKMeaccxIhpRhzzjmpFGPOOeeclJIx55xzTkrJmHPOOSelZMw555yTUjrnnHMO"
+		+ "SimldM4556SUUkLonHNSSimdc845AQBABQ4AAAE2imxOMBJUaMhKACAVAMDgOJalaZ4niqZpSZKmeZ4n"
+		+ "mqZpapKkaZ4niqZpmjzP80RRFE1TVXme54miKJqmqnJdURRN0zRNVSXLoiiKpqmqqgrTNE3TVFVVhWma"
+		+ "pmmqquvCtlVVVV3XdWHbqqqqruu6wHVd13VlGbiu67quLAsAAE9wAAAqsGF1hJOiscBCQ1YCABkAAIQx"
+		+ "CCmEEFIGIaQQQkgphZAAAIABBwCAABPKQKEhKwGAcAAAgBCMMcYYY4wxNoxhjDHGGGOMMXEKY4wxxhhj"
+		+ "jDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhj"
+		+ "jDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHG2FprrbVWABjOhQNA"
+		+ "WYSNM6wknRWOBhcashIACAkAAIxBiDHoJJSSSkoVQow5KCWVllqKrUKIMQilpNRabDEWzzkHoaSUWoop"
+		+ "tuI556Sk1FqMMcZaXAshpZRaiy22GJtsIaSUUmsxxlpjM0q1lFqLMcYYayxKuZRSa7HFGGuNRSibW2sx"
+		+ "xlprrTUp5XNLsdVaY6y1JqOMkjHGWmustdYilFIyxhRTrLXWmoQwxvcYY6wx51qTEsL4HlMtsdVaa1JK"
+		+ "KSNkjanGWnNOSglljI0t1ZRzzgUAQD04AEAlGEEnGVUWYaMJFx6AQkNWAgC5AQAIQkoxxphzzjnnnHMO"
+		+ "UqQYc8w55yCEEEIIIaQIMcaYc85BCCGEEEJIGWPMOecghBBCCKGEklLKmHPOQQghhFJKKSWl1DnnIIQQ"
+		+ "QiillFJKSqlzzkEIIYRSSimllJRSCCGEEEIIpZRSSikppZRCCCGEEkoppZRSUkophRBCCKWUUkoppaSU"
+		+ "UgohhBBKKaWUUkpJKaUUQgmllFJKKaWUklJKKaUQSimllFJKKSWllFJKpZRSSimllFJKSimllEoppZRS"
+		+ "SimllJRSSimVUkoppZRSSikppZRSSqmUUkoppZRSUkoppZRSKaWUUkoppaSUUkoppVJKKaWUUkpJKaWU"
+		+ "UkqllFJKKaWUklJKKaWUUiqllFJKKaUAAKADBwCAACMqLcROM648AkcUMkxAhYasBADIAAAQB7G01lqr"
+		+ "jHLKSUmtQ0Ya5qCk2EkHIbVYS2UgQcpJSp2CCCkGqYWMKqWYk5ZCy5hSDGIrMXSMMUc55VRCxxgAAACC"
+		+ "AAADETITCBRAgYEMADhASJACAAoLDB3DRUBALiGjwKBwTDgnnTYAAEGIzBCJiMUgMaEaKCqmA4DFBYZ8"
+		+ "AMjQ2Ei7uIAuA1zQxV0HQghCEIJYHEABCTg44YYn3vCEG5ygU1TqQAAAAAAAHgDgAQAg2QAiIqKZ4+jw"
+		+ "+AAJERkhKTE5QREAAAAAADsA+AAASFKAiIho5jg6PD5AQkRGSEpMTlACAAABBAAAAABAAAEICAgAAAAA"
+		+ "AAQAAAAICE9nZ1MAAMAzAAAAAAAA12AAAAIAAAAQIhJlHjJMWVr/Mv89/0r/UP9O/07/PP87/yj/Hv8s"
+		+ "/xT/FEwdl5tJHgTj1XG5wc7FNGE8TlenIkVyBgAA4PwvppJZ1J37Xf21rorjO/aQd5/1wnEAdB3du46c"
+		+ "lFBPW0fyAfSIhKN/gLIVBACPiwDrlx+W8frlbCXU41W/qedrwXGvi1fLGiI5ZJkJnnNY+o7fK+g4zECx"
+		+ "JYxwKcJ3FloJAOw5/ft6QNRqFxSSM1ycCpd6xNz7TvFtp7Y7TjbzIFIxKUkBoMOP7t+hqhG8Wi4bP/OA"
+		+ "X35zWKeYcNWiBnK/lk++PTebHOrxR6/I0sDQCum6mZkCvtdJAdAejF7tUSVU73ViaOCfuo1HDYH0rzOO"
+		+ "pBqq/y9AI0ke2G8uDQOgBsiZNIxOCNmjhmyVwbZzMN4308KY2/LnQ/+9NeCVFMZv6saHsz/zmrRYtAI2"
+		+ "/cESGEA0wgoAOngFeJv0bwUwdjWZQRUbtcZcGnOqvHLvFfM9SHwDoHC1P/vOcLS7ZgEAoAfgNEIC8vzG"
+		+ "F2BpTBE6bAUI6hNAZG9P82p0EMLCwFSAcMdAAAAAMkJAjm9YLqZooHGujca3m7Jp/zGZPPpxON7m9HXr"
+		+ "L8oCH98a0wDAhfda8F3JgdENmvQtkyvw7tBqL8/Z+WEbAEgBkOBVUkxnV1xmdIFccknb6z7bC8AuV2Tm"
+		+ "P0e4zM5MNTdL/9adO2nItonlK1tj0aaK7lVDj7i1wcuyLGdpzZLlxXJapUqKEM3VGD63cByv3p7z2O47"
+		+ "Of/D/9M1zU2H47G5eYU8Bx4AoK4FoBqAxAEcCMA0ABwAAKaYnr3zi2oPSQFgKMcDAACr8K04RkYGAAAA"
+		+ "UAcAAAS3ASC+BAASIAB+WNXyprmFswoaO2J4KjxWvTtm/LMxDO5ZC5+A+YUkvwEA2sBHjx7mWGwDAGDk"
+		+ "QgL2ldd/Hw2WojAcvqsA2BEwDwUICS4MtBMQpriDAggAYM8AlKeXg8MHmPNriXfLp6niN6+tzf34cv78"
+		+ "633eZiCuOpzuXwEAvX6n3uNXmv79/sPk7Wq4+p0CEABCpmRfste+OZsTlwoAhNu0GxRgwPfKolpY0GVG"
+		+ "PDMkSZ0qrnJ56yhDlU1qcPdMf2jS9ETPJvy44Kb2EueZzkp64jLxEvGurtti+i46aluXay23q5724P64"
+		+ "P+fKL3jrd5/lAQAA8Nh57ng48Bz09vceMgCAdtYAdJwFAMC44hwDQFYzzwsAAEAYt/40Fd4rXCkAwDQ0"
+		+ "0EO/igMAcHD2DAAAAAAo2gKAzn5yAQASAGugNAAgPuhc9OVG76gWnBkdY/MlUoiH0cOdB+6oicYzGTc/"
+		+ "cyD9CgDw+W5rDBk9doIgSZCX///aCfyl3SkAAGtSL5j67PgLAEBIdIwDgP70EsIkHCf4AxAu7gAAADgr"
+		+ "QLnRZuAe99md7zs+zsrpNtNo2CTydP3itF3S5Qx+bXvjeCQAXgaI784A5AKgAAiZn6aPHQDwpPHlVAQE"
+		+ "Mw+lZAAY9L6h7zZcnJemA9vs0WL5/FM/SX0zsXDy86J7ioHZm1v/+gJOzTSQfsU0X4MuT3riVk0OVQxw"
+		+ "4GQLGcO+O/RzW+GA2L4rNAUAAAxQ1NDv05362a42eJKVC8vPtgLTbjYb5u3lKQE83xgoFVN0q4D7RzNF"
+		+ "V2vdBcNjA5bZuwEGDgcAAOD8CQwJfACABwAAAIA5PBQAAAAA9ACQIQBoAOATAQAAAAD1CgC+/eETAABe"
+		+ "CF3948jyOuj7DEOHivklQ7YQuvX7UfxZbbTfwcb8Tzp/BQBYZAaE3cq/u3oE3KzOcJ9HZyu4ePvDyw4A"
+		+ "sFMFf4Xw4gQOAMLFHQAAAAAil2hv08JOXwLmYN19gtuOfFFCaU+rvr55AGC5lzi7fDwpIPkPASADwB9A"
+		+ "LoXtujH6Om0EIFPceQevMoLYKyI1FQBkTKq37w9cSHx4Pn96++FWow/ZfvvlA8/K9J7b58N/eGYs7r77"
+		+ "isftxs9z/tb8EwvNIj1zsjjfFeBAfaz26a17ca1paqDAQFovAABQkJWHiuZar58/A5/+mK+7WbYRmdP+"
+		+ "c1MjZeu8jqjsOK8sZ+37xVVMOxMYqKumwLVGlBhmKchm3iJHMP7TuSu8AwCPiYbgI1cHAAAAALLflQQA"
+		+ "AAAAAAAcLQAAAAAAOACAagCuE98AAAAAiKcAmD6cBxQAAJ4HHen1RpdXi+aMpAwhm/ec2PYYr1WJxrs5"
+		+ "vBiI9xsA4IKC+1ErPI8Kcgagub3/28MJHCu544BmPV8C89lQ5ysBCB87AI0RP+6N8IkL1IBwxwAAAJAH"
+		+ "oP24kUI+GjwdDH/J6vz7rmS2ic3D6r+dvtb4fe54NFuk7RVeC2R7ungn+naZS/EKFw/b0Au5AKX79TWj"
+		+ "JK9/bAEoAJBQQpW+MqmymwE8bTv5E9cuvWKivEFOAZATJ7z94qUjDgUX3QPNX7/PMMBb1CjZDHQei/J5"
+		+ "RmuaPkic3J0nCwZIdvemCXoAVJlTtxcd2vUOZJaWOzPkbfWxx4H9wkxuJZ9ftZNDBx6CwMXoqamMnCQO"
+		+ "+d1d7Ai8myL3cqGuRBdngDcOAAAApoYUARgAAAAA3A/9h30AAAAAABzrAQAAAEhA1gMAAwD6xwAAAADA"
+		+ "YwPADgAAAL7nPMTlJrrVuDZPdCoy30WIBTqvdNdhQq+20Z5xutgU84ED/isAwKP8AYMZGlZ+GS/X1XGA"
+		+ "u1drgflW0PlKAKIjFbyPqAhTABsIdwwAAAAA0o1Ykrn7uouD8UvH8HA7MbT5sJde+X3m/KvSmNMVPFTm"
+		+ "9RdsFsKJ7ddoDEAA4L6plA7/szi4PjZ0/zOJw6EKgKZtxhe3/Jmp+N5/63S63urLO5zxu396eNaffW5o"
+		+ "kCcPfZuow8tMke0uPk+Xd0X+zcV0GlrTUzdTw9ReqPNe2aWhSSj2FpsbZmsMVWWgfspagktVwdLTZRGW"
+		+ "h3688l26tZcfS+JXXaX5OCqf4UpIKJKqM53e1SZnPV2jx4vJTj9Z/bThktx/+gEAMBsy3wUHAAAAABnl"
+		+ "nwwAAAAAAHQLAADWAwANAFwP/fnwx2ILALweAAAAAMD+HAB4TlEAAL7n3MrbTEu7pI37ZIeK+ZCBf695"
+		+ "kcdBPta+Be3OMszMiCzwGwDgooE7HKkAVKcC3KXhOKDJ334AnVkFhSFaEqYIBYFjAAAAAOCy2DLI5wOy"
+		+ "svK+OMi5TUvc5C65v+v9ReujhePpfBjv8jb0ilHak1Dt/SZMlftWc6BZQm9loIwECgK0uZMuAk+m1VEK"
+		+ "sLbh/d/llwxsnobNU+A+o28EQ0b1z5xdtoiL+pl/J4f1eyL9q/5ubnbTzMZLAgwNlTWnAUbDjCssCt9L"
+		+ "bBJ4KfLf31SOnokabyfIl+dviK3tm9wQCoGeXH539sxN0vOLAxl5WIZ9t06/PXrFU+MBEG/5s7Vf0AAA"
+		+ "AAcAAAAA6NP9p4hojyr9+i8/ndL7HQAAAAAA0GkBAABoLQAAAMy7+jsbAICbBADgPABv1AgDAD7HvOLz"
+		+ "JkKqbI3duR4VM0FWao55YfstU6ttzVMxg1q4bwCA0+OJu/sTRYDCpydQVlZn+IuYD6/CIPxUgUTICVYQ"
+		+ "7hgAAAAMgMbStlZmbwd0b2w914/tg25vDx1I9Jfl233Rfl9LSJwK5u5F6xs7gobk5MF0f629DRSytN3/"
+		+ "fe6TkkFDj2qC17OlD/z5AGR823vx2d8un9RBhyrAuqWnk+lf7+htemef6nRUa5uAgE9pp+6oFGB3FVVR"
+		+ "/Jl/sbHJ3UWeJBBg7GeSHc0pl3N2PqOuLrTMz0nBk75Z7dzbZcTkYqiqrRtNqSdgl5vcTOSTmbjXbPlM"
+		+ "Np81OSuY3Kbm79jzsce8BViAZdn8//rLLhygAQAAAIBrVgAAAAAAKIwBAAAA4AAAgJp892M1AABcAAAA"
+		+ "AIBfAYAALgAA3sY8wXZqoV3DVrt72dkMyArlLV9ymeu09mXDu5eVMluYvwEQACcwj6ZACQB23/P47Slg"
+		+ "KmvSRkMEwjo2AdjfJ3BABkIkAAAAAGzfTGJhWXMbe7uz/gnHJyZG9i/loNn2V9V/evTRZ6bnU3IMiq81"
+		+ "B3N/m+DSFQhd6L3EVLYH8AXpmNf9mb3XJcpC1j/oovlJqYoAJtvAZPULdQ3m+/ld2Aw6k32ylp1u93Sc"
+		+ "dAxTsMlN0ZM4oPmv31/qEBDdZDYAMHZ225PrGdLEnbFsutYZ8846K//+N7v60OwcPVk0+aV1gh8Xs7yv"
+		+ "gvQDruv8TR8Pe/LgZw696GkyWWCABJHYODwAHs4Oe/cXAEwDAAAAAPKDCwBAAwDAAwCAzo9vfiYALAMA"
+		+ "8CVgAP7GvODLXFV6pWicrKRgJeOON7bMzO7t22jcK2awhW9fAQDuE8A5wNOBI0BlOMMP820IgzCXKDIQ"
+		+ "AgAAAACoT15y0/+7txj9O/NicH0m9pWX/nZUfPbqQ7imb3KjTdj6roVCo9NhH4EHCjAadxkhbVWADEDG"
+		+ "OIsj/LjB7dK8dbjfkZcfO56uu89Oh2rslpm/93k90EOH5hj+DIjjPX3yQ23WonIq2qcOI7LLKIjX26TI"
+		+ "nX9K8fHtGKgg6v3r4O4fyuTpbLutXqL0Xb2iRKioLAaBk1yHykoiEqm8sOmoV2AcP+U8YPjzZHugaBp5"
+		+ "Dh4AWAzTxw0AOAAAAABAvrMAYCY6yfQbTkEQAFgBAAAAAFgaAAAABuJRJAAsAACoAR63fNHjKJW7lqbN"
+		+ "CwNY8XwzvsAy82nt92jel4vfmcFWuH0FADiajjgEAMC6JjbDh4HQkhDDMRASBAAAAADZfPJhLjlvbv6+"
+		+ "3psxM3r/eRkBgGfqTRXwAI7aA2+c+bDPL2P/6FO2lXR5/fAW9m99P3vFyogYtY7IKt/zNFdi0owd/24A"
+		+ "CiLs//iscQF4u7Kh/W73VNXh+sSS3mwj785ihoq8VK991bI/Byc5hXcHM+E9/cuh5Q3tQU/nlDAFmWif"
+		+ "mmmCqRSO283l/CyL0uq5Xsn18FNumXv3ncooyaBSlACbjw/0DtvlaBTR0gSem6Vny32unl09StQFh6Ey"
+		+ "i1LBlDWsN0Bg+PM+BwA4AAAwOBQAAMOj35z/6g8AAACOAhQAAPTvqAEA+KsDBAsA3nZ8EOuhl1UatfmS"
+		+ "TVKyUTjTjC9unuFWc1C+nUKzUdw3AMAjisAjocgYAGbvK//zcARsaU1stEo4CF8YoMMICOAYCAcAAAAc"
+		+ "QMYNzZPMofWDWp1dK28rD+5uvOFa+3r7m5zo70bfhu+ezNvea6rKcsq9jT/J5BAghJueihQPABAIgzNL"
+		+ "Ql/MOABwYlfN0u3rbz1HHRfm7hA651N864C0cpTBHMrRCucucsmhoEn4NGmUA9O/PPMKD9YzuqB64rpa"
+		+ "wuOkc1mYPZe0zHW5ozt8yI4WJEaH4dUBtBpc1ApA52QCWmdyfCj29GB8J3oDpjtYewS+s/uWON0JxAD/"
+		+ "BgDaDQAAAEBFwJAAADj3eSgAAADQAgB+Z/wDx9kqq3CtjH7UTlKulbjO+C3PuR7p0i7GeJEiWPH2FQDg"
+		+ "AJz22ToSa6sGQgsD7i4IEcAxEAIAAAAA5M5rsHNWGS1dDpjJqaV9MwBACP4w/jdCtz3POoAwZU/7UVDE"
+		+ "MqYMa3j7ZmX3O/r8aSRD1oP6+5Wn3f3B/86L913+YfPhJJu/PxUd0LHqzWKpAuMBIMm4GRLm8CaRuKc9"
+		+ "OfM4T/4ss48qfV45qwVNlIoizTzNH54Xi2Cq5cSYUu7a2dPTM1p7svfR9P4Oy+6JIo3eZ5qVrhyyIsPh"
+		+ "cQNMvl2AZQE5T3Wa9lUDywqiX40A6DE+rtPs+f5we3wIAJb1fqYBgBEAAHAAAE8BANCfON8GACgLAk9n"
+		+ "Z1MABI9FAAAAAAAA12AAAAMAAAA80+lLBfnXAQEBfmb8BONBl5bRnJ3rSCmQhVdm/CDXubilSjBLVEgp"
+		+ "wn8DAFSOn+C9EwUA+9kJDE2soYKEQGhJQAiOgQAAAADIBIhL3Ywmd30rf4/Xqu1vZPaZx80ZzuPkVL7u"
+		+ "LXL3N+9lFBr7NO+8byVWN5w+dyF4ArmInp4L1BqtWwAZiAesc8W5/pmJGaCryY1imGLmQLRcm7NnKZKT"
+		+ "ve+siU6SaPnXUSsNvNOGAvBvNlBwyvnBFsbnNLvFXJrew/a77NzR4eflpJp35yTe2YZmlhFkLwCAx90B"
+		+ "O5eQ/vI5w/jpgAcAAHAAAGw5AOCRyKs81/YAAHCAAQAAqHCtBOAAPmb8g+q8T6804p5zXyA0ZvyL2yyW"
+		+ "dW0HR2F4axqQRbXm5KOH20MBs4/MqoIAQCgjpBAEAAAAAP/fyiDOdHoccpv5bZtvr29nXeXs8+ns3thn"
+		+ "wTnfeTi/ky6Wi9P1hZf3jNilgm6280RqceAB+6umGRjJw/GQ9zPM8/K8dMZSLGBxvLy+HXo68sqPaPMa"
+		+ "P6ZqNx8lq+yRkdG6WEbhYlkA01PJ1FW7s7TP/1mXWZubheZq8+rq6uq/q1cCz4EDANZmAABg5emTVX0F"
+		+ "AADA+zAAAAAwBVztbAIODg4="
+		/*}}}*/
+	);
+
+	var Beep = function()
+	{
+		// Beep Async
+		setTimeout(function() {
+			bAudio.pause();
+			bAudio.currentTime = 0;
+			bAudio.play();
+		}, 0 );
+	};
+
 	ns[ NS_EXPORT ]( EX_FUNC, "Message", Message );
 	ns[ NS_EXPORT ]( EX_FUNC, "Error", Error );
+	ns[ NS_EXPORT ]( EX_FUNC, "Beep", Beep );
 })();
diff --git a/botanjs/src/externs/Components.Vim.Cursor.js b/botanjs/src/externs/Components.Vim.Cursor.js
index 13b5624..ec39afc 100644
--- a/botanjs/src/externs/Components.Vim.Cursor.js
+++ b/botanjs/src/externs/Components.Vim.Cursor.js
@@ -38,6 +38,8 @@ Components.Vim.Cursor.X;
 /** @type Number */
 Components.Vim.Cursor.Y;
 /** @type Number */
+Components.Vim.Cursor.aPos;
+/** @type Number */
 Components.Vim.Cursor.cols;
 /** @type message */
 Components.Vim.Cursor.string;