diff --git a/botanjs/src/Components/Vim/Actions/DELETE.js b/botanjs/src/Components/Vim/Actions/DELETE.js
index 113a4179..c42b2efa 100644
--- a/botanjs/src/Components/Vim/Actions/DELETE.js
+++ b/botanjs/src/Components/Vim/Actions/DELETE.js
@@ -1,13 +1,24 @@
 (function(){
 	var ns = __namespace( "Components.Vim.Actions" );
 
+	/** @type {System.Debug} */
+	var debug = __import( "System.Debug" );
+
+	/** @type {Components.Vim.State.Stator} */
+	var Stator                                 = __import( "Components.Vim.State.Stator" );
+	/** @type {Components.Vim.State.Stack} */
+	var Stack                                  = __import( "Components.Vim.State.Stack" );
+
 	var Mesg = __import( "Components.Vim.Message" );
 
+	var occurence = __import( "System.utils.Perf.CountSubstr" );
+
 	/** @type {Components.Vim.Cursor.IAction} */
 	var DELETE = function( Cursor )
 	{
 		/** @type {Components.Vim.Cursor} */
 		this.__cursor = Cursor;
+		this.__nline = 0;
 	};
 
 	DELETE.prototype.allowMovement = true;
@@ -17,15 +28,65 @@
 
 	};
 
-	DELETE.prototype.handler = function( e )
+	DELETE.prototype.handler = function( e, sp )
 	{
 		e.preventDefault();
 
+		/** @type {Components.Vim.State.Registers} */
+		var reg = e.target.registers;
+
+		var cur = this.__cursor;
+		var feeder = cur.feeder;
+
+		var c = feeder.content;
+
+		var s = sp;
+		var e = cur.aPos;
+
+		if( e < s )
+		{
+			s = cur.aPos;
+			e = sp;
+		}
+
+		var removed = c.substring( s, e + 1 );
+		reg.change( removed );
+
+		this.__nline = occurence( removed, "\n" );
+
+		feeder.content = c.substring( 0, s ) + c.substring( e + 1 );
+
+		var stator = new Stator( cur, s );
+		var stack = new Stack();
+
+		c = c[ e + 1 ];
+		if( c == "\n" || c == undefined )
+		{
+			cur.suppressEvent();
+			cur.moveX( -1 );
+			cur.unsuppressEvent();
+		}
+
+		var f = stator.save( 0, removed );
+		stack.store( function() {
+			f();
+			// Offset correction after REDO / UNDO
+			cur.moveX( 1 );
+		} );
+
+		cur.rec.record( stack );
+
+		feeder.pan();
 	};
 
 	DELETE.prototype.getMessage = function()
 	{
-		return "<TODO> DELETE COMMAND";
+		if( this.__nline )
+		{
+			return Mesg( "LINE_FEWER", this.__nline );
+		}
+
+		return "";
 	};
 
 	ns[ NS_EXPORT ]( EX_CLASS, "DELETE", DELETE );
diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js
index a199a5f5..e67f083c 100644
--- a/botanjs/src/Components/Vim/Actions/INSERT.js
+++ b/botanjs/src/Components/Vim/Actions/INSERT.js
@@ -2,9 +2,11 @@
 	var ns = __namespace( "Components.Vim.Actions" );
 
 	/** @type {Components.Vim.State.Stack} */
-	var Stack                                 = __import( "Components.Vim.State.Stack" );
+	var Stack                                  = __import( "Components.Vim.State.Stack" );
+	/** @type {Components.Vim.State.Stator} */
+	var Stator                                 = __import( "Components.Vim.State.Stator" );
 	/** @type {System.Debug} */
-	var debug                                 = __import( "System.Debug" );
+	var debug                                  = __import( "System.Debug" );
 
 	var Mesg = __import( "Components.Vim.Message" );
 
@@ -27,7 +29,7 @@
 		/** @type {Components.Vim.Cursor} */
 		this.__cursor = Cursor;
 
-		this.__startState = this.__saveCur();
+		this.__Stator = new Stator( Cursor );
 
 		// Initialize this stack
 		this.__rec( "", true );
@@ -35,66 +37,12 @@
 
 	INSERT.prototype.allowMovement = false;
 
-	INSERT.prototype.__saveCur = function()
-	{
-		var c = this.__cursor;
-		var obj = {
-			p: c.P
-			, x: c.X
-			, y: c.Y
-			, px: c.feeder.panX
-			, py: c.feeder.panY
-		};
-
-		if( 0 < obj.x )
-		{
-			obj.p -= 1;
-			obj.x -= 1;
-		}
-
-		return obj;
-	}
-
 	INSERT.prototype.dispose = function()
 	{
 		this.__cursor.moveX( -1 );
 		this.__rec( "", true );
 	};
 
-	INSERT.prototype.__storeState = function()
-	{
-		var cur = this.__cursor;
-		var feeder = cur.feeder;
-		var insertLength = this.__insertLength;
-		var contentUndo = this.__contentUndo;
-		var startPos = this.__startPosition;
-		var sSt = this.__startState;
-		var eSt = this.__saveCur();
-
-		var st = sSt;
-		// Calling this repeatedly will swap between UNDO / REDO state
-		return function() {
-			var contentRedo = feeder.content.substr( startPos, insertLength );
-			feeder.content =
-				feeder.content.substring( 0, startPos )
-				+ contentUndo
-				+ feeder.content.substring( startPos + insertLength );
-			insertLength = contentUndo.length;
-			contentUndo = contentRedo;
-
-			cur.PStart = st.p;
-			cur.PEnd = st.p + 1;
-			cur.X = st.x;
-			cur.Y = st.y;
-			feeder.panX = st.px;
-			feeder.panY = st.py;
-
-			feeder.pan();
-
-			st = ( st == sSt ) ? eSt : sSt;
-		};
-	};
-
 	INSERT.prototype.__rec = function( c, newRec )
 	{
 		if( newRec || !this.__stack )
@@ -107,7 +55,7 @@
 				) return;
 
 				this.__stack.store(
-					this.__storeState()
+					this.__Stator.save( this.__insertLength, this.__contentUndo )
 				);
 
 				this.__cursor.rec.record( this.__stack );
@@ -116,7 +64,6 @@
 			this.__insertLength = 0;
 			this.__contentUndo = "";
 			this.__stack = new Stack();
-			this.__startPosition = this.__cursor.aPos;
 		}
 
 		if( c == "\n" )
@@ -132,45 +79,37 @@
 		var cur = this.__cursor;
 		var feeder = cur.feeder;
 
-		switch( e.keyCode )
+		// Backspace
+		if( e.kMap( "BS" ) )
 		{
-			case 8: // Backspace
-				var oY = feeder.panY + cur.Y;
-				if( cur.X == 0 && feeder.panY == 0 && cur.Y == 0 ) return;
+			var oY = feeder.panY + cur.Y;
+			if( cur.X == 0 && feeder.panY == 0 && cur.Y == 0 ) return;
 
-				cur.moveX( -1, true, true );
+			cur.moveX( -1, true, true );
 
-				var f = cur.aPos;
+			var f = cur.aPos;
 
-				if( this.__insertLength <= 0 )
-				{
-					this.__contentUndo = feeder.content.substr( f, 1 ) + this.__contentUndo;
-					this.__startPosition --;
-				}
-				else
-				{
-					this.__insertLength --;
-				}
+			if( this.__insertLength <= 0 )
+			{
+				this.__contentUndo = feeder.content.substr( f, 1 ) + this.__contentUndo;
+				this.__insertLength --;
+			}
 
-				feeder.content =
-					feeder.content.substring( 0, f )
-					+ feeder.content.substring( f + 1 );
-
-				break;
-			case 46: // Delete
-				var f = cur.aPos;
-
-				this.__contentUndo += feeder.content.substr( f, 1 );
-
-				feeder.content =
-					feeder.content.substring( 0, f )
-					+ feeder.content.substring( f + 1 );
-
-				break;
-			default:
-				// Do nothing
-				return;
+			feeder.content =
+				feeder.content.substring( 0, f )
+				+ feeder.content.substring( f + 1 );
 		}
+		else if( e.kMap( "Del" ) )
+		{
+			var f = cur.aPos;
+
+			this.__contentUndo += feeder.content.substr( f, 1 );
+
+			feeder.content =
+				feeder.content.substring( 0, f )
+				+ feeder.content.substring( f + 1 );
+		}
+		else return;
 
 		feeder.pan();
 		feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js
index ab9671bf..659b058c 100644
--- a/botanjs/src/Components/Vim/Actions/VISUAL.js
+++ b/botanjs/src/Components/Vim/Actions/VISUAL.js
@@ -23,6 +23,7 @@
 		this.__leaveMesg = "";
 
 		Cursor.blink = false;
+		Cursor.pSpace = true;
 	};
 
 	VISUAL.prototype.allowMovement = true;
@@ -31,6 +32,7 @@
 	{
 		this.__msg = this.__leaveMesg;
 		this.__cursor.blink = true;
+		this.__cursor.pSpace = false;
 		this.__cursor.PStart = this.__selStart;
 		this.__cursor.PEnd = this.__selStart + 1;
 	};
@@ -41,27 +43,18 @@
 
 		if( e.ModKeys ) return;
 
+		var cur = this.__cursor;
 		var Action = null;
 		switch( true )
 		{
 			case e.kMap( "y" ):
-				Action = new YANK( this.__cursor );
+				Action = new YANK( cur );
 				break;
 			case e.kMap( "d" ):
-				Action = new DELETE( this.__cursor );
+				Action = new DELETE( cur );
 				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;
 
@@ -78,6 +71,18 @@
 			this.__selStart = prevPos;
 		}
 
+		if( Action )
+		{
+			cur.suppressEvent();
+			Action.handler( e, this.__startaP );
+			this.__leaveMesg = Action.getMessage();
+			Action.dispose();
+			cur.unsuppressEvent();
+
+			this.__selStart = cur.PStart;
+			return true;
+		}
+
 		cur.PStart = prevPos;
 		cur.PEnd = newPos;
 	};
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index ce1e9471..7bcc195a 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -14,6 +14,7 @@
 	var KEY_ALT = 18;
 
 	var BACKSPACE = 8;
+	var DELETE = 46;
 
 	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;
@@ -31,6 +32,8 @@
 	var F6 = 117; var F7 = 118; var F8 = 119; var F9 = 120; var F10 = 121;
 	var F11 = 122; var F12 = 123;
 
+	var COMMA = 188; var FULLSTOP = 190;
+
 	var __maps = {};
 	var Map = function( str )
 	{
@@ -62,6 +65,9 @@
 		var kCode;
 		switch( sCode )
 		{
+			case "BS": kCode = Mod + BACKSPACE; break;
+			case "Del": kCode = Mod + DELETE; break;
+
 			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;
@@ -99,8 +105,11 @@
 			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;
+			case "<": Mod = SHIFT; case ",": kCode = Mod + COMMA; break;
+			case ">": Mod = SHIFT; case ".": kCode = Mod + FULLSTOP; break;
+
 			default:
-				throw new Error( "No such keys: " + str );
+				throw new Error( "Unsupport keys: " + str );
 		}
 
 		return __maps[ str ] = kCode;
@@ -209,7 +218,7 @@
 		var ccur = this.__ccur;
 
 		var x = ccur.X;
-		ccur.moveX( a, b, c );
+		ccur.moveX( a, b, c || ccur.pSpace );
 		if( ccur.X == x ) beep();
 	};
 
@@ -245,7 +254,7 @@
 		var cursorHandled = true;
 		switch( kCode )
 		{
-			case BACKSPACE: this.__cMoveX( -1, true ); break; // Backspace, go back 1 char, regardless of line
+			case BACKSPACE: this.__cMoveX( -1, true ); break; // Backspace, go back 1 char
 			case H: this.__cMoveX( -1 ); break; // Left
 			case L: this.__cMoveX( 1 ); break; // Right
 			case K: this.__cMoveY( -1 ); break; // Up
@@ -259,7 +268,7 @@
 				ccur.lineStart();
 				break;
 			case SHIFT + _4: // $, End
-				ccur.lineEnd();
+				ccur.lineEnd( ccur.pSpace );
 				break;
 			case SHIFT + G: // Goto last line
 				ccur.moveY( Number.MAX_VALUE );
@@ -293,10 +302,10 @@
 	 * */
 	Controls.prototype.handler = function( sender, e )
 	{
-		// Neve capture these keys
-		if( e.ModKeys
+		// Never capture these keys
+		if( e.keyCode == ( ALT + D )
 			// F2 - F12
-			|| ( F1 < e.keyCode && e.keyCode < 124 )
+			|| ( F1 < e.keyCode && e.keyCode <= F12 )
 		) return;
 
 		// Clear composite command
@@ -334,36 +343,32 @@
 			return;
 		}
 
-		if( this.__cursorCommand( e ) )
-		{
-			e.preventDefault();
-			return;
-		}
+		e.preventDefault();
 
-		if( this.__actionCommand( e ) )
-		{
-			e.preventDefault();
-			return;
-		}
+		if( this.__cursorCommand( e ) ) return;
+		if( this.__actionCommand( e ) ) return;
 	};
 
-	var InputEvent = function( e )
+	var InputEvent = function( sender, e )
 	{
 		this.__e = e;
+		this.__target = sender;
 
 		var c = this.__e.keyCode;
 
 		this.__escape = c == ESC || ( e.ctrlKey && c == C );
 		this.__kCode = c
 			+ ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
-			+ ( e.ctrlKey ? CTRL : 0 );
+			+ ( e.ctrlKey ? CTRL : 0 )
+			+ ( e.altKey ? ALT : 0 );
 
 		this.__modKeys = c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
 		this.__key = e.key;
 	};
 
- 	__readOnly( InputEvent.prototype, "key", function() { return this.__key; } );
- 	__readOnly( InputEvent.prototype, "keyCode", function() { return this.__kCode; } );
+	__readOnly( InputEvent.prototype, "target", function() { return this.__target; } );
+	__readOnly( InputEvent.prototype, "key", function() { return this.__key; } );
+	__readOnly( InputEvent.prototype, "keyCode", function() { return this.__kCode; } );
 	__readOnly( InputEvent.prototype, "ModKeys", function() { return this.__modKeys; } );
 	__readOnly( InputEvent.prototype, "Escape", function() { return this.__escape; } );
 
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index 0481f305..5f99f5da 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -80,6 +80,9 @@
 		this.action = null;
 
 		this.blink = true;
+		this.pSpace = false;
+
+		this.__suppEvt = 0;
 	};
 
 	// Set by VimArea
@@ -118,12 +121,12 @@
 		// Include empty lines befor cursor end
 		if( ( phantomSpace && cLen - 1 <= x ) || ( cLen == 1 && c == undefined ) )
 		{
-			x = d > 0 ? cLen - 1 : 0;
+			x = 0 < d ? cLen - 1 : 0;
 		}
 		// ( 2 < cLen ) Exclude empty lines at cursor end
-		else if( ( 2 < cLen && x == cLen - 1 && c == " " ) || c == undefined )
+		else if( ( 2 <= cLen && x == cLen - 1 && c == " " ) || c == undefined )
 		{
-			x = d > 0 ? cLen - 2 : 0;
+			x = 0 < d ? cLen - 2 : 0;
 		}
 		else if( c == "\n" )
 		{
@@ -158,6 +161,16 @@
 		this.PEnd = P + 1;
 		this.__p = P;
 
+		this.__fireUpdate();
+	};
+
+	Cursor.prototype.__fireUpdate = function()
+	{
+		if( 0 < this.__suppEvt )
+		{
+			debug.Info( "Event suppressed, suppression level is: " + this.__suppEvt );
+			return;
+		}
 		this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
 	};
 
@@ -270,7 +283,7 @@
 		this.action = new (Actions[ name ])( this );
 		this.__pulseMsg = null;
 
-		this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+		this.__fireUpdate();
 	};
 
 	Cursor.prototype.closeAction = function()
@@ -280,7 +293,7 @@
 		this.__pulseMsg = this.action.getMessage();
 		this.action = null;
 
-		this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+		this.__fireUpdate();
 	};
 
 	// Open, Run, then close an action
@@ -292,9 +305,12 @@
 		this.__pulseMsg = action.getMessage();
 		action.dispose();
 
-		this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+		this.__fireUpdate();
 	};
 
+	Cursor.prototype.suppressEvent = function() { ++ this.__suppEvt; };
+	Cursor.prototype.unsuppressEvent = function() { -- this.__suppEvt; };
+
 	Cursor.prototype.getLine = function()
 	{
 		var feeder = this.feeder;
diff --git a/botanjs/src/Components/Vim/State/Stator.js b/botanjs/src/Components/Vim/State/Stator.js
new file mode 100644
index 00000000..a17687d5
--- /dev/null
+++ b/botanjs/src/Components/Vim/State/Stator.js
@@ -0,0 +1,71 @@
+(function(){
+	var ns = __namespace( "Components.Vim.State" );
+
+	var Stator = function( cur, start )
+	{
+		this.__cursor = cur;
+		this.__startPosition = start == undefined ? cur.aPos : start;
+		this.__startState = this.__saveCur();
+	};
+
+	Stator.prototype.save = function( insertLength, contentUndo )
+	{
+		var cur = this.__cursor;
+		var feeder = cur.feeder;
+		var startPos = this.__startPosition;
+
+		if( insertLength < 0 )
+		{
+			startPos += insertLength;
+			insertLength = 0;
+		}
+
+		var sSt = this.__startState;
+		var eSt = this.__saveCur();
+
+		var st = sSt;
+		// Calling this repeatedly will swap between UNDO / REDO state
+		return function() {
+			var contentRedo = feeder.content.substr( startPos, insertLength );
+			feeder.content =
+				feeder.content.substring( 0, startPos )
+				+ contentUndo
+				+ feeder.content.substring( startPos + insertLength );
+			insertLength = contentUndo.length;
+			contentUndo = contentRedo;
+
+			cur.PStart = st.p;
+			cur.PEnd = st.p + 1;
+			cur.X = st.x;
+			cur.Y = st.y;
+			feeder.panX = st.px;
+			feeder.panY = st.py;
+
+			feeder.pan();
+
+			st = ( st == sSt ) ? eSt : sSt;
+		};
+	};
+
+	Stator.prototype.__saveCur = function()
+	{
+		var c = this.__cursor;
+		var obj = {
+			p: c.PStart
+			, x: c.X
+			, y: c.Y
+			, px: c.feeder.panX
+			, py: c.feeder.panY
+		};
+
+		if( 0 < obj.x )
+		{
+			obj.p -= 1;
+			obj.x -= 1;
+		}
+
+		return obj;
+	};
+
+	ns[ NS_EXPORT ]( EX_CLASS, "Stator", Stator );
+})();
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 368cecbe..54c78649 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -32,7 +32,7 @@
 			if ( e.keyCode ) code = e.keyCode;
 			else if ( e.which ) code = e.which;
 
-			handler( sender, new InputEvent( e ) );
+			handler( sender, new InputEvent( sender, e ) );
 		};
 	};
 
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 04060da4..f9e572ed 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -17,6 +17,8 @@
 
 		, "UNDO_LIMIT": "Already at oldest change"
 		, "REDO_LIMIT": "Already at newest change"
+
+		, "LINE_FEWER": "%1 fewer lines"
 	};
 
 	var errors = {
diff --git a/botanjs/src/externs/Components.Vim.Controls.InputEvent.js b/botanjs/src/externs/Components.Vim.Controls.InputEvent.js
index ffd085ee..a8e1bdb0 100644
--- a/botanjs/src/externs/Components.Vim.Controls.InputEvent.js
+++ b/botanjs/src/externs/Components.Vim.Controls.InputEvent.js
@@ -1,6 +1,8 @@
 /** @constructor */
 Components.Vim.Controls.InputEvent = function(){};
 
+/** @type {Components.Vim.VimArea} */
+Components.Vim.Controls.InputEvent.target;
 /** @type String */
 Components.Vim.Controls.InputEvent.key;
 /** @type Boolean */
diff --git a/botanjs/src/externs/Components.Vim.Cursor.js b/botanjs/src/externs/Components.Vim.Cursor.js
index 76fef9d5..2f42cdb4 100644
--- a/botanjs/src/externs/Components.Vim.Cursor.js
+++ b/botanjs/src/externs/Components.Vim.Cursor.js
@@ -26,9 +26,15 @@ Components.Vim.Cursor.openAction;
 Components.Vim.Cursor.openRunAction;
 /** @type Function */
 Components.Vim.Cursor.closeAction;
+/** @type Function */
+Components.Vim.Cursor.suppressEvent;
+/** @type Function */
+Components.Vim.Cursor.unsuppressEvent;
 
 /** @type {Boolean} */
 Components.Vim.Cursor.blink;
+/** @type {Boolean} */
+Components.Vim.Cursor.pSpace;
 /** @type {Array} */
 Components.Vim.Cursor.lineBuffers;
 /** @type Number */