commit e52c312af5f72ab345105ac17d636a87c5a5bbb7
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2016-03-21T18:08:07Z |
| subject | added g8, v ( hightlight only ) |
commit e52c312af5f72ab345105ac17d636a87c5a5bbb7
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2016-03-21T18:08:07Z
added g8, v ( hightlight only )
Some structural changes on VimControls
---
botanjs/src/Components/Vim/Actions/INSERT.js | 5 +-
botanjs/src/Components/Vim/Actions/PRINT_HEX.js | 52 +++++
botanjs/src/Components/Vim/Actions/VISUAL.js | 67 ++++++
botanjs/src/Components/Vim/Controls.js | 277 +++++++++++++-----------
botanjs/src/Components/Vim/Cursor.js | 15 +-
botanjs/src/Components/Vim/VimArea.js | 14 +-
botanjs/src/externs/Components.Vim.Cursor.js | 6 +-
botanjs/src/externs/Components.Vim.IAction.js | 3 +
8 files changed, 304 insertions(+), 135 deletions(-)
diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js
index e6d4615..a199a5f 100644
--- a/botanjs/src/Components/Vim/Actions/INSERT.js
+++ b/botanjs/src/Components/Vim/Actions/INSERT.js
@@ -33,6 +33,8 @@
this.__rec( "", true );
};
+ INSERT.prototype.allowMovement = false;
+
INSERT.prototype.__saveCur = function()
{
var c = this.__cursor;
@@ -80,7 +82,8 @@
insertLength = contentUndo.length;
contentUndo = contentRedo;
- cur.P = st.p;
+ cur.PStart = st.p;
+ cur.PEnd = st.p + 1;
cur.X = st.x;
cur.Y = st.y;
feeder.panX = st.px;
diff --git a/botanjs/src/Components/Vim/Actions/PRINT_HEX.js b/botanjs/src/Components/Vim/Actions/PRINT_HEX.js
new file mode 100644
index 0000000..c3efbbb
--- /dev/null
+++ b/botanjs/src/Components/Vim/Actions/PRINT_HEX.js
@@ -0,0 +1,52 @@
+(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" );
+
+ /** @type {Components.Vim.Cursor.IAction} */
+ var PRINT_HEX = function( Cursor )
+ {
+ /** @type {Components.Vim.Cursor} */
+ this.__cursor = Cursor;
+ };
+
+ PRINT_HEX.prototype.dispose = function()
+ {
+ };
+
+ PRINT_HEX.prototype.handler = function( e )
+ {
+ e.preventDefault();
+ var str = unescape( encodeURIComponent( this.__cursor.feeder.content[ this.__cursor.aPos ] ) );
+ var l = str.length;
+ var msg = [];
+ for( var i = 0; i < l; i ++ )
+ {
+ msg[i] = str[i] == "\n"
+ ? "a"
+ : str.charCodeAt( i ).toString( 16 )
+ ;
+
+ if( msg[i].length == 1 )
+ {
+ msg[i] = "0" + msg[i];
+ }
+ else if( msg[i].length == 0 )
+ {
+ msg[i] = "00";
+ }
+ }
+
+ this.__msg = msg.join( " " );
+ };
+
+ PRINT_HEX.prototype.getMessage = function()
+ {
+ return this.__msg;
+ };
+
+ ns[ NS_EXPORT ]( EX_CLASS, "PRINT_HEX", PRINT_HEX );
+})();
diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js
new file mode 100644
index 0000000..752eaec
--- /dev/null
+++ b/botanjs/src/Components/Vim/Actions/VISUAL.js
@@ -0,0 +1,67 @@
+(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 Mesg = __import( "Components.Vim.Message" );
+
+ /** @type {Components.Vim.Cursor.IAction} */
+ var VISUAL = function( Cursor )
+ {
+ /** @type {Components.Vim.Cursor} */
+ this.__cursor = Cursor;
+ this.__startaP = Cursor.aPos;
+ this.__start = Cursor.PStart;
+ this.__selStart = Cursor.PStart;
+
+ Cursor.blink = false;
+ };
+
+ VISUAL.prototype.allowMovement = true;
+
+ VISUAL.prototype.dispose = function()
+ {
+ this.__cursor.blink = true;
+ this.__cursor.PStart = this.__selStart;
+ this.__cursor.PEnd = this.__selStart + 1;
+ };
+
+
+ VISUAL.prototype.handler = function( e )
+ {
+ e.preventDefault();
+
+ if( [ 16, 17, 18 ].indexOf( e.keyCode ) != -1 ) return;
+ var cur = this.__cursor;
+ var prevPos = this.__start;
+ var newPos = cur.PStart;
+
+ var posDiff = newPos - prevPos;
+ if( 0 <= posDiff )
+ {
+ this.__selStart = newPos;
+ newPos = newPos + 1;
+ }
+ else if( posDiff < 0 )
+ {
+ prevPos += posDiff;
+ newPos = this.__start + 1;
+ this.__selStart = prevPos;
+ }
+
+ cur.PStart = prevPos;
+ cur.PEnd = newPos;
+ };
+
+ VISUAL.prototype.getMessage = function()
+ {
+ var msg = Mesg( "VISUAL" );
+
+ return msg;
+ };
+
+ ns[ NS_EXPORT ]( EX_CLASS, "VISUAL", VISUAL );
+})();
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 7f37de7..f55181b 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -7,6 +7,10 @@
var SHIFT = 1 << 9;
var CTRL = 1 << 10;
+ var KEY_SHIFT = 16;
+ var KEY_CTRL = 17;
+ var KEY_ALT = 18;
+
var BACKSPACE = 8;
var _0 = 48; var _1 = 49; var _2 = 50; var _3 = 51; var _4 = 52;
@@ -29,132 +33,62 @@
{
/** @type {Components.Vim.VimArea} */
this.__vimArea = vimArea
- this.__keyChains = [];
- };
-
- Controls.prototype.__comboG = function( keyCode )
- {
- var keyON = this.__keyChains[ 0 ] == G;
- if( keyON )
- {
- var cursor = this.__vimArea.contentFeeder.cursor;
- switch( keyCode )
- {
- case G:
- cursor.moveY( -Number.MAX_VALUE );
- cursor.moveX( -Number.MAX_VALUE, true );
- this.__keyChains = [];
- return true;
- default:
- this.__keyChains = [];
- beep();
- return true;
- }
- }
- else if( keyCode == G )
- {
- this.__keyChains[ 0 ] = G;
- return true;
- }
-
- return false;
- };
-
- Controls.prototype.__comboT = function( e ) { return false; };
- Controls.prototype.__comboD = function( e ) { return false; };
-
- // <
- Controls.prototype.__comboLeftShift = function( e ) { return false; };
- // >
- Controls.prototype.__comboRightShift = function( e ) { return false; };
+ this.__cfeeder = vimArea.contentFeeder;
+ this.__sfeeder = vimArea.statusFeeder;
- Controls.prototype.__comboKey = function( e )
- {
- return this.__comboG( e )
- || this.__comboD( e )
- || this.__comboT( e )
- || this.__comboLeftShift( e )
- || this.__comboRightShift( e );
+ this.__ccur = this.__cfeeder.cursor;
};
- Controls.prototype.handler = function( sender, e )
+ Controls.prototype.__comp = function( kCode, handler )
{
- // Neve capture these keys
- if( e.altKey
- // F2 - F12
- || ( F1 < e.keyCode && e.keyCode < 124 )
- ) return;
-
- var vArea = this.__vimArea;
- // Action Mode handled by the actions themselves
- var cfeeder = vArea.contentFeeder;
-
- // Esc OR Ctrl + c
- var Escape = e.keyCode == ESC || ( e.ctrlKey && e.keyCode == C );
-
- // Clear the keychains in combo commands
- if( Escape && this.__keyChains.length )
+ if( handler )
{
- this.__keyChains = [];
- beep();
- return;
+ if( !this.__compReg ) this.__compReg = [];
+ this.__compReg.push({
+ keys: Array.prototype.slice.call( arguments, 2 )
+ , handler: handler
+ , i: 0
+ });
+ return true;
}
- if( cfeeder.cursor.action )
+ for( var i = 0; i < this.__compReg.length; i ++ )
{
- if( Escape )
- {
- e.preventDefault();
- cfeeder.cursor.closeAction();
- }
- else
+ var compReg = this.__compReg[i];
+ var keys = compReg.keys;
+
+ if( keys[ compReg.i ++ ] == kCode )
{
- cfeeder.cursor.action.handler( e );
+ if( compReg.i == keys.length )
+ {
+ compReg.handler();
+ compReg = null;
+ this.__cMovement = false;
+ }
+
+ return true;
}
- return;
}
- e.preventDefault();
- var kCode = e.keyCode
- + ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
- + ( e.ctrlKey ? CTRL : 0 );
-
- // Handles long commands
-
- if( this.__comboKey( kCode ) ) return;
-
- var cfeeder = vArea.contentFeeder;
- var sfeeder = vArea.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();
- }
- };
+ if( this.__compReg ) beep();
+ this.__compReg = null;
+ this.__cMovement = false;
+ return false;
+ };
+ Controls.prototype.__actionCommand = function( e, kCode )
+ {
var ActionHandled = true;
- // Action Commands
+ var ccur = this.__ccur;
+
+ // Action Command
switch( kCode )
{
case SHIFT + A: // Append at the line end
ccur.lineEnd();
case A: // Append
- cMoveX( 1, true, true );
+ this.__cMoveX( 1, true, true );
case I: // Insert
ccur.openAction( "INSERT" );
break;
@@ -177,22 +111,67 @@
case SHIFT + K: // Find the manual entry
break;
+ case V: // Visual
+ ccur.openAction( "VISUAL" );
+ break;
+ case SHIFT + V: // Visual line
+ ccur.openAction( "VISUAL_LINE" );
+ break;
+
case F1: // F1, help
break;
default:
ActionHandled = false;
}
- if( ActionHandled ) return;
+ return ActionHandled;
+ };
- // Cursor Commands
+ Controls.prototype.__cMoveX = function( a, b, c )
+ {
+ var ccur = this.__ccur;
+
+ var x = ccur.X;
+ ccur.moveX( a, b, c );
+ if( ccur.X == x ) beep();
+ };
+
+ Controls.prototype.__cMoveY = function( a )
+ {
+ var ccur = this.__ccur;
+ var cfeeder = this.__cfeeder;
+
+ var y = ccur.Y + cfeeder.panY;
+ ccur.moveY( a );
+ if( y == ( ccur.Y + cfeeder.panY ) )
+ {
+ if( 0 < a && !cfeeder.EOF ) return;
+ beep();
+ }
+ };
+
+ Controls.prototype.__cursorCommand = function( e, kCode )
+ {
+ if( this.__cMovement && this.__comp )
+ {
+ var k = e.keyCode;
+ if(!( k == KEY_SHIFT || k == KEY_CTRL || k == KEY_ALT ))
+ {
+ this.__comp( kCode );
+ return true;
+ }
+ }
+
+ var ccur = this.__ccur;
+
+ var cursorHandled = true;
switch( kCode )
{
- case BACKSPACE: cMoveX( -1, true ); break; // Backspace, go back 1 char, regardless of line
- case H: cMoveX( -1 ); break; // Left
- case L: cMoveX( 1 ); break; // Right
- case K: cMoveY( -1 ); break; // Up
- case J: cMoveY( 1 ); break; // Down
+ case BACKSPACE: this.__cMoveX( -1, true ); break; // Backspace, go back 1 char, regardless of line
+ case H: this.__cMoveX( -1 ); break; // Left
+ case L: this.__cMoveX( 1 ); break; // Right
+ case K: this.__cMoveY( -1 ); break; // Up
+ case J: this.__cMoveY( 1 ); break; // Down
case SHIFT + H: // First line buffer
break;
@@ -207,24 +186,78 @@
case SHIFT + G: // Goto last line
ccur.moveY( Number.MAX_VALUE );
ccur.moveX( Number.MAX_VALUE, true );
- break;
+ break
case SHIFT + _5: // %, Find next item
break;
+
+ case G: // Go to top
+ this.__cMovement = true;
+ this.__comp( kCode, function(){
+ ccur.moveY( -Number.MAX_VALUE );
+ ccur.moveX( -Number.MAX_VALUE, true );
+ }, G );
+ this.__comp( kCode, function(){
+ ccur.openRunAction( "PRINT_HEX", e );
+ }, _8 );
+ break;
+
+ default:
+ cursorHandled = false;
}
+ return cursorHandled;
+ };
- // Integrated commands
- switch( kCode )
+ Controls.prototype.handler = function( sender, e )
+ {
+ // Neve capture these keys
+ if( e.altKey
+ // F2 - F12
+ || ( F1 < e.keyCode && e.keyCode < 124 )
+ ) return;
+
+ // Esc OR Ctrl + c
+ var Escape = e.keyCode == ESC || ( e.ctrlKey && e.keyCode == C );
+
+ // Clear composite command
+ if( Escape && this.__compReg )
{
- case V: // Visual
- ccur.openAction( "VISUAL" );
- break;
- case SHIFT + V: // Visual line
- ccur.openAction( "VISUAL_LINE" );
- break;
+ this.__compReg = null;
+ this.__cMovement = false;
+ beep();
+ return;
}
+ var cfeeder = this.__cfeeder;
+ var ccur = this.__ccur;
+
+ var kCode = e.keyCode
+ + ( e.shiftKey || e.getModifierState( "CapsLock" ) ? SHIFT : 0 )
+ + ( e.ctrlKey ? CTRL : 0 );
+
+ // Action commands are handled by the actions themselves
+ if( ccur.action )
+ {
+ if( Escape )
+ {
+ e.preventDefault();
+ ccur.closeAction();
+ }
+ else
+ {
+ if( ccur.action.allowMovement )
+ this.__cursorCommand( e, kCode );
+
+ ccur.action.handler( e );
+ }
+ return;
+ }
+
+ e.preventDefault();
+
+ if( this.__cursorCommand( e, kCode ) ) return;
+ if( this.__actionCommand( e, kCode ) ) return;
};
ns[ NS_EXPORT ]( EX_CLASS, "Controls", Controls );
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index f4b6d9b..51377a5 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -71,12 +71,15 @@
this.Y = 0;
// The resulting position
- this.P = 0;
+ this.PStart = 0;
+ this.PEnd = 1;
// State recorder
this.rec = new Recorder();
this.action = null;
+
+ this.blink = true;
};
// Can only be 1, -1
@@ -147,7 +150,11 @@
Cursor.prototype.updatePosition = function()
{
- this.P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
+ var P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
+ this.PStart = P;
+ this.PEnd = P + 1;
+ this.__p = P;
+
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
};
@@ -383,8 +390,8 @@
__readOnly( Cursor.prototype, "position", function()
{
return {
- start: this.P
- , end: this.P + 1
+ start: this.PStart
+ , end: this.PEnd
};
} );
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 8452fab..8ecb7a9 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -53,12 +53,6 @@
var _self = this;
- var controls = new VimControls( this );
- stage.addEventListener(
- "KeyDown"
- , KeyHandler( this, controls.handler.bind( controls ) )
- );
-
stage.addEventListener( "Focus", function() { _self.__active = true; } );
stage.addEventListener( "Blur", function() { _self.__active = false; } );
@@ -141,11 +135,17 @@
Cycle.perma( "VimCursorBlinkCycle" + element.id, function()
{
_self.select(
- ( _self.__blink = !_self.__blink )
+ !_self.__cursor.blink || ( _self.__blink = !_self.__blink )
? _self.__cursor.position
: { start: 0, end: 0 }
);
}, 600 );
+
+ var controls = new VimControls( this );
+ this.stage.addEventListener(
+ "KeyDown"
+ , KeyHandler( this, controls.handler.bind( controls ) )
+ );
};
__readOnly( VimArea.prototype, "content", function() {
diff --git a/botanjs/src/externs/Components.Vim.Cursor.js b/botanjs/src/externs/Components.Vim.Cursor.js
index ec39afc..0873383 100644
--- a/botanjs/src/externs/Components.Vim.Cursor.js
+++ b/botanjs/src/externs/Components.Vim.Cursor.js
@@ -25,12 +25,16 @@ Components.Vim.Cursor.openRunAction;
/** @type Function */
Components.Vim.Cursor.closeAction;
+/** @type {Boolean} */
+Components.Vim.Cursor.blink;
/** @type {Array} */
Components.Vim.Cursor.lineBuffers;
/** @type Number */
Components.Vim.Cursor.pX;
/** @type Number */
-Components.Vim.Cursor.P;
+Components.Vim.Cursor.PStart;
+/** @type Number */
+Components.Vim.Cursor.PEnd;
/** @type Number */
Components.Vim.Cursor.aX;
/** @type Number */
diff --git a/botanjs/src/externs/Components.Vim.IAction.js b/botanjs/src/externs/Components.Vim.IAction.js
index db82c97..22571a7 100644
--- a/botanjs/src/externs/Components.Vim.IAction.js
+++ b/botanjs/src/externs/Components.Vim.IAction.js
@@ -7,3 +7,6 @@ Components.Vim.IAction.dispose;
Components.Vim.IAction.handler;
/** @type Function */
Components.Vim.IAction.getMessage;
+
+/** @type Boolean */
+Components.Vim.IAction.allowMovement;