forked from Botanical/BotanJS
Merge remote-tracking branches 'origin/master' and 'vim/master' into Astro
This commit is contained in:
commit
c6e4bdc509
112
botanjs/src/Components/Vim/Actions/DELETE.js
Normal file
112
botanjs/src/Components/Vim/Actions/DELETE.js
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
(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;
|
||||||
|
this.__startX = Cursor.aPos;
|
||||||
|
};
|
||||||
|
|
||||||
|
DELETE.prototype.allowMovement = true;
|
||||||
|
|
||||||
|
DELETE.prototype.dispose = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
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 Triggered = false;
|
||||||
|
if( sp == undefined && this.__startX != cur.aPos )
|
||||||
|
{
|
||||||
|
Triggered = true;
|
||||||
|
|
||||||
|
if( e.kMap( "l" ) )
|
||||||
|
{
|
||||||
|
cur.moveX( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
sp = this.__startX;
|
||||||
|
}
|
||||||
|
else if( sp == undefined ) return;
|
||||||
|
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
return Triggered;
|
||||||
|
};
|
||||||
|
|
||||||
|
DELETE.prototype.getMessage = function()
|
||||||
|
{
|
||||||
|
if( this.__nline )
|
||||||
|
{
|
||||||
|
return Mesg( "LINE_FEWER", this.__nline );
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "DELETE", DELETE );
|
||||||
|
})();
|
@ -2,9 +2,11 @@
|
|||||||
var ns = __namespace( "Components.Vim.Actions" );
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
/** @type {Components.Vim.State.Stack} */
|
/** @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} */
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
var Mesg = __import( "Components.Vim.Message" );
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
|
||||||
@ -27,40 +29,20 @@
|
|||||||
/** @type {Components.Vim.Cursor} */
|
/** @type {Components.Vim.Cursor} */
|
||||||
this.__cursor = Cursor;
|
this.__cursor = Cursor;
|
||||||
|
|
||||||
this.__startX = Cursor.aPos;
|
this.__Stator = new Stator( Cursor );
|
||||||
|
|
||||||
// Initialize this stack
|
// Initialize this stack
|
||||||
this.__rec( "", true );
|
this.__rec( "", true );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
INSERT.prototype.allowMovement = false;
|
||||||
|
|
||||||
INSERT.prototype.dispose = function()
|
INSERT.prototype.dispose = function()
|
||||||
{
|
{
|
||||||
this.__cursor.moveX( -1 );
|
this.__cursor.moveX( -1 );
|
||||||
this.__rec( "", true );
|
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 startX = this.__startX;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
feeder.pan();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
INSERT.prototype.__rec = function( c, newRec )
|
INSERT.prototype.__rec = function( c, newRec )
|
||||||
{
|
{
|
||||||
if( newRec || !this.__stack )
|
if( newRec || !this.__stack )
|
||||||
@ -73,7 +55,7 @@
|
|||||||
) return;
|
) return;
|
||||||
|
|
||||||
this.__stack.store(
|
this.__stack.store(
|
||||||
this.__storeState()
|
this.__Stator.save( this.__insertLength, this.__contentUndo )
|
||||||
);
|
);
|
||||||
|
|
||||||
this.__cursor.rec.record( this.__stack );
|
this.__cursor.rec.record( this.__stack );
|
||||||
@ -82,7 +64,6 @@
|
|||||||
this.__insertLength = 0;
|
this.__insertLength = 0;
|
||||||
this.__contentUndo = "";
|
this.__contentUndo = "";
|
||||||
this.__stack = new Stack();
|
this.__stack = new Stack();
|
||||||
this.__startPosition = this.__cursor.aPos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( c == "\n" )
|
if( c == "\n" )
|
||||||
@ -98,45 +79,37 @@
|
|||||||
var cur = this.__cursor;
|
var cur = this.__cursor;
|
||||||
var feeder = cur.feeder;
|
var feeder = cur.feeder;
|
||||||
|
|
||||||
switch( e.keyCode )
|
// Backspace
|
||||||
|
if( e.kMap( "BS" ) )
|
||||||
{
|
{
|
||||||
case 8: // Backspace
|
var oY = feeder.panY + cur.Y;
|
||||||
var oY = feeder.panY + cur.Y;
|
if( cur.X == 0 && feeder.panY == 0 && cur.Y == 0 ) return;
|
||||||
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 )
|
if( this.__insertLength <= 0 )
|
||||||
{
|
{
|
||||||
this.__contentUndo = feeder.content.substr( f, 1 ) + this.__contentUndo;
|
this.__contentUndo = feeder.content.substr( f, 1 ) + this.__contentUndo;
|
||||||
this.__startPosition --;
|
this.__insertLength --;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
this.__insertLength --;
|
|
||||||
}
|
|
||||||
|
|
||||||
feeder.content =
|
feeder.content =
|
||||||
feeder.content.substring( 0, f )
|
feeder.content.substring( 0, f )
|
||||||
+ feeder.content.substring( f + 1 );
|
+ 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;
|
|
||||||
}
|
}
|
||||||
|
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.pan();
|
||||||
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
@ -163,12 +136,23 @@
|
|||||||
+ inputChar
|
+ inputChar
|
||||||
+ feeder.content.substring( f );
|
+ feeder.content.substring( f );
|
||||||
|
|
||||||
feeder.pan();
|
if( inputChar == "\n" )
|
||||||
|
{
|
||||||
|
feeder.softReset();
|
||||||
|
feeder.pan();
|
||||||
|
cur.moveY( 1 );
|
||||||
|
cur.lineStart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
feeder.pan();
|
||||||
|
cur.moveX( 1, false, true );
|
||||||
|
}
|
||||||
|
|
||||||
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
|
|
||||||
this.__rec( inputChar );
|
this.__rec( inputChar );
|
||||||
|
|
||||||
cur.moveX( 1 );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
INSERT.prototype.getMessage = function()
|
INSERT.prototype.getMessage = function()
|
||||||
|
52
botanjs/src/Components/Vim/Actions/PRINT_HEX.js
Normal file
52
botanjs/src/Components/Vim/Actions/PRINT_HEX.js
Normal file
@ -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 );
|
||||||
|
})();
|
114
botanjs/src/Components/Vim/Actions/VISUAL.js
Normal file
114
botanjs/src/Components/Vim/Actions/VISUAL.js
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
|
/** @type {System.Debug} */
|
||||||
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
|
||||||
|
/** @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 )
|
||||||
|
{
|
||||||
|
/** @type {Components.Vim.Cursor} */
|
||||||
|
this.__cursor = Cursor;
|
||||||
|
this.__startaP = Cursor.aPos;
|
||||||
|
this.__startP = { x: Cursor.X, y: Cursor.Y, p: Cursor.P };
|
||||||
|
this.__start = Cursor.PStart;
|
||||||
|
this.__selStart = Cursor.PStart;
|
||||||
|
this.__msg = Mesg( "VISUAL" );
|
||||||
|
this.__leaveMesg = "";
|
||||||
|
|
||||||
|
Cursor.blink = false;
|
||||||
|
Cursor.pSpace = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
VISUAL.prototype.allowMovement = true;
|
||||||
|
|
||||||
|
VISUAL.prototype.dispose = function()
|
||||||
|
{
|
||||||
|
this.__msg = this.__leaveMesg;
|
||||||
|
this.__cursor.blink = true;
|
||||||
|
this.__cursor.pSpace = false;
|
||||||
|
this.__cursor.PStart = this.__selStart;
|
||||||
|
this.__cursor.PEnd = this.__selStart + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
VISUAL.prototype.handler = function( e, done )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if( e.ModKeys ) return;
|
||||||
|
|
||||||
|
var cur = this.__cursor;
|
||||||
|
var Action = null;
|
||||||
|
|
||||||
|
if( e.kMap( "y" ) )
|
||||||
|
{
|
||||||
|
Action = new YANK( cur );
|
||||||
|
}
|
||||||
|
else if( e.kMap( "d" ) )
|
||||||
|
{
|
||||||
|
Action = new DELETE( cur );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Action )
|
||||||
|
{
|
||||||
|
cur.suppressEvent();
|
||||||
|
|
||||||
|
// Low-level cursor position adjustment
|
||||||
|
// this swap the cursor direction from LTR to RTL
|
||||||
|
// i.e. treat all delete as "e<----s" flow
|
||||||
|
// to keep the cursor position as the top on UNDO / REDO
|
||||||
|
if( Action.constructor == DELETE && this.__startaP < cur.aPos )
|
||||||
|
{
|
||||||
|
this.__startaP = cur.aPos;
|
||||||
|
cur.X = this.__startP.x;
|
||||||
|
cur.Y = this.__startP.y;
|
||||||
|
cur.P = this.__startP.p;
|
||||||
|
}
|
||||||
|
|
||||||
|
Action.handler( e, this.__startaP );
|
||||||
|
this.__leaveMesg = Action.getMessage();
|
||||||
|
|
||||||
|
Action.dispose();
|
||||||
|
cur.unsuppressEvent();
|
||||||
|
|
||||||
|
this.__selStart = cur.PStart;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
return this.__msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "VISUAL", VISUAL );
|
||||||
|
})();
|
32
botanjs/src/Components/Vim/Actions/YANK.js
Normal file
32
botanjs/src/Components/Vim/Actions/YANK.js
Normal file
@ -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 );
|
||||||
|
})();
|
@ -1,13 +1,20 @@
|
|||||||
(function(){
|
(function(){
|
||||||
var ns = __namespace( "Components.Vim" );
|
var ns = __namespace( "Components.Vim" );
|
||||||
|
|
||||||
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
var beep = ns[ NS_INVOKE ]( "Beep" );
|
var beep = ns[ NS_INVOKE ]( "Beep" );
|
||||||
|
|
||||||
var SHIFT = 1 << 9;
|
var SHIFT = 1 << 9;
|
||||||
var CTRL = 1 << 10;
|
var CTRL = 1 << 10;
|
||||||
|
var ALT = 1 << 11;
|
||||||
|
|
||||||
|
var KEY_SHIFT = 16;
|
||||||
|
var KEY_CTRL = 17;
|
||||||
|
var KEY_ALT = 18;
|
||||||
|
|
||||||
var BACKSPACE = 8;
|
var BACKSPACE = 8;
|
||||||
|
var DELETE = 46;
|
||||||
|
|
||||||
var _0 = 48; var _1 = 49; var _2 = 50; var _3 = 51; var _4 = 52;
|
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;
|
var _5 = 53; var _6 = 54; var _7 = 55; var _8 = 56; var _9 = 57;
|
||||||
@ -19,151 +26,159 @@
|
|||||||
var U = 85; var V = 86; var W = 87; var X = 88; var Y = 89;
|
var U = 85; var V = 86; var W = 87; var X = 88; var Y = 89;
|
||||||
var Z = 90;
|
var Z = 90;
|
||||||
|
|
||||||
|
var S_BRACKET_L = 219; var S_BRACKET_R = 221;
|
||||||
|
|
||||||
|
var ESC = 27;
|
||||||
|
|
||||||
|
var F1 = 112; var F2 = 113; var F3 = 114; var F4 = 115; var F5 = 116;
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
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 "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;
|
||||||
|
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;
|
||||||
|
case "<": Mod = SHIFT; case ",": kCode = Mod + COMMA; break;
|
||||||
|
case ">": Mod = SHIFT; case ".": kCode = Mod + FULLSTOP; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error( "Unsupport keys: " + str );
|
||||||
|
}
|
||||||
|
|
||||||
|
return __maps[ str ] = kCode;
|
||||||
|
};
|
||||||
|
|
||||||
var Controls = function( vimArea )
|
var Controls = function( vimArea )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.VimArea} */
|
/** @type {Components.Vim.VimArea} */
|
||||||
this.__vimArea = vimArea
|
this.__vimArea = vimArea
|
||||||
this.__keyChains = [];
|
|
||||||
|
this.__cfeeder = vimArea.contentFeeder;
|
||||||
|
this.__sfeeder = vimArea.statusFeeder;
|
||||||
|
|
||||||
|
this.__ccur = this.__cfeeder.cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
Controls.prototype.__comboG = function( keyCode )
|
Controls.prototype.__comp = function( kCode, handler )
|
||||||
{
|
{
|
||||||
var keyON = this.__keyChains[ 0 ] == G;
|
if( handler )
|
||||||
if( keyON )
|
|
||||||
{
|
{
|
||||||
var cursor = this.__vimArea.contentFeeder.cursor;
|
if( !this.__compReg ) this.__compReg = [];
|
||||||
switch( keyCode )
|
this.__compReg.push({
|
||||||
{
|
keys: Array.prototype.slice.call( arguments, 2 )
|
||||||
case G:
|
, handler: handler
|
||||||
cursor.moveY( -Number.MAX_VALUE );
|
, i: 0
|
||||||
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 true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( var i = 0; i < this.__compReg.length; i ++ )
|
||||||
|
{
|
||||||
|
var compReg = this.__compReg[i];
|
||||||
|
var keys = compReg.keys;
|
||||||
|
|
||||||
|
if( keys[ compReg.i ++ ] == kCode )
|
||||||
|
{
|
||||||
|
if( compReg.i == keys.length )
|
||||||
|
{
|
||||||
|
compReg.handler();
|
||||||
|
this.__compReg = null;
|
||||||
|
this.__cMovement = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this.__compReg ) beep();
|
||||||
|
this.__compReg = null;
|
||||||
|
this.__cMovement = false;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Controls.prototype.__comboT = function( e ) { return false; };
|
Controls.prototype.__actionCommand = function( e )
|
||||||
|
|
||||||
// <
|
|
||||||
Controls.prototype.__comboLeftShift = function( e ) { return false; };
|
|
||||||
|
|
||||||
// >
|
|
||||||
Controls.prototype.__comboRightShift = function( e ) { return false; };
|
|
||||||
|
|
||||||
Controls.prototype.__comboKey = function( e )
|
|
||||||
{
|
{
|
||||||
return this.__comboG( e )
|
var ActionHandled = true;
|
||||||
|| this.__comboT( e )
|
var ccur = this.__ccur;
|
||||||
|| this.__comboLeftShift( e )
|
|
||||||
|| this.__comboRightShift( e );
|
|
||||||
};
|
|
||||||
|
|
||||||
Controls.prototype.handler = function( sender, e )
|
// Action Command
|
||||||
{
|
switch( e.keyCode )
|
||||||
// Neve capture these keys
|
|
||||||
if( e.altKey
|
|
||||||
// F2 - F12
|
|
||||||
|| ( 112 < 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 == 27 || ( e.ctrlKey && e.keyCode == 67 );
|
|
||||||
|
|
||||||
// Clear the keychains in combo commands
|
|
||||||
if( Escape && this.__keyChains.length )
|
|
||||||
{
|
{
|
||||||
this.__keyChains = [];
|
case SHIFT + A: // Append at the line end
|
||||||
beep();
|
ccur.lineEnd();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( cfeeder.cursor.action )
|
|
||||||
{
|
|
||||||
if( Escape )
|
|
||||||
{
|
|
||||||
e.preventDefault();
|
|
||||||
cfeeder.cursor.closeAction();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cfeeder.cursor.action.handler( e );
|
|
||||||
}
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
switch( kCode )
|
|
||||||
{
|
|
||||||
// Cursor movements
|
|
||||||
case BACKSPACE: // Backspace, go back 1 char, regardless of line
|
|
||||||
cMoveX( -1, true );
|
|
||||||
break;
|
|
||||||
case H: // Left
|
|
||||||
cMoveX( -1 );
|
|
||||||
break;
|
|
||||||
case L: // Right
|
|
||||||
cMoveX( 1 );
|
|
||||||
break;
|
|
||||||
case K: // Up
|
|
||||||
cMoveY( -1 );
|
|
||||||
break;
|
|
||||||
case J: // Down
|
|
||||||
cMoveY( 1 );
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Insert
|
|
||||||
case A: // Append
|
case A: // Append
|
||||||
cMoveX( 1, true, true );
|
this.__cMoveX( 1, true, true );
|
||||||
ccur.openAction( "INSERT" );
|
|
||||||
break;
|
|
||||||
case I: // Insert
|
case I: // Insert
|
||||||
|
ccur.openAction( "INSERT" );
|
||||||
break;
|
break;
|
||||||
case U: // Undo
|
case U: // Undo
|
||||||
ccur.openRunAction( "UNDO", e );
|
ccur.openRunAction( "UNDO", e );
|
||||||
@ -171,9 +186,10 @@
|
|||||||
case CTRL + R: // Redo
|
case CTRL + R: // Redo
|
||||||
ccur.openRunAction( "REDO", e );
|
ccur.openRunAction( "REDO", e );
|
||||||
break;
|
break;
|
||||||
case X: // Del
|
case D: // Del with motion
|
||||||
|
ccur.openAction( "DELETE" );
|
||||||
break;
|
break;
|
||||||
case SHIFT + A: // Append at the line end
|
case X: // Del
|
||||||
break;
|
break;
|
||||||
case SHIFT + X: // Delete before
|
case SHIFT + X: // Delete before
|
||||||
break;
|
break;
|
||||||
@ -181,37 +197,223 @@
|
|||||||
break;
|
break;
|
||||||
case SHIFT + I: // Append before the line start, after spaces
|
case SHIFT + I: // Append before the line start, after spaces
|
||||||
break;
|
break;
|
||||||
|
case SHIFT + J: // Join lines
|
||||||
|
break;
|
||||||
|
case SHIFT + K: // Find the manual entry
|
||||||
|
break;
|
||||||
|
|
||||||
case SHIFT + G: // Goto last line
|
case V: // Visual
|
||||||
ccur.moveY( Number.MAX_VALUE );
|
ccur.openAction( "VISUAL" );
|
||||||
ccur.moveX( Number.MAX_VALUE, true );
|
|
||||||
break;
|
break;
|
||||||
// remove characters
|
case SHIFT + V: // Visual line
|
||||||
case X: // Remove in cursor
|
ccur.openAction( "VISUAL_LINE" );
|
||||||
break;
|
break;
|
||||||
case SHIFT + X: // Remove before cursor
|
|
||||||
|
case F1: // F1, help
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
ActionHandled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionHandled;
|
||||||
|
};
|
||||||
|
|
||||||
|
Controls.prototype.__cMoveX = function( a, b, c )
|
||||||
|
{
|
||||||
|
var ccur = this.__ccur;
|
||||||
|
|
||||||
|
var x = ccur.X;
|
||||||
|
ccur.moveX( a, b, c || ccur.pSpace );
|
||||||
|
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 )
|
||||||
|
{
|
||||||
|
var kCode = e.keyCode;
|
||||||
|
|
||||||
|
if( this.__cMovement && this.__comp )
|
||||||
|
{
|
||||||
|
if( !e.ModKeys )
|
||||||
|
{
|
||||||
|
this.__comp( kCode );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var ccur = this.__ccur;
|
||||||
|
|
||||||
|
var cursorHandled = true;
|
||||||
|
switch( kCode )
|
||||||
|
{
|
||||||
|
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
|
||||||
|
case J: this.__cMoveY( 1 ); break; // Down
|
||||||
|
|
||||||
case SHIFT + H: // First line buffer
|
case SHIFT + H: // First line buffer
|
||||||
break;
|
break;
|
||||||
case SHIFT + L: // Last line buffer
|
case SHIFT + L: // Last line buffer
|
||||||
break;
|
break;
|
||||||
case SHIFT + _4: // $, End
|
|
||||||
ccur.lineEnd();
|
|
||||||
break;
|
|
||||||
case SHIFT + _5: // %, Find next item
|
|
||||||
break;
|
|
||||||
case SHIFT + _6: // ^, Start
|
case SHIFT + _6: // ^, Start
|
||||||
ccur.lineStart();
|
ccur.lineStart();
|
||||||
break;
|
break;
|
||||||
case SHIFT + J: // Join lines
|
case SHIFT + _4: // $, End
|
||||||
|
ccur.lineEnd( ccur.pSpace );
|
||||||
break;
|
break;
|
||||||
case SHIFT + K: // manual entry
|
case SHIFT + G: // Goto last line
|
||||||
|
ccur.moveY( Number.MAX_VALUE );
|
||||||
|
ccur.moveX( Number.MAX_VALUE, true );
|
||||||
|
break
|
||||||
|
|
||||||
|
case SHIFT + _5: // %, Find next item
|
||||||
break;
|
break;
|
||||||
case 112: // F1, help
|
case T: // To
|
||||||
|
break;
|
||||||
|
case I: // In between boundary
|
||||||
|
if( !ccur.action )
|
||||||
|
{
|
||||||
|
cursorHandled = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__cMovement = true;
|
||||||
|
// Word boundary
|
||||||
|
this.__comp( kCode, function(){
|
||||||
|
debug.Info( "Word boundary" );
|
||||||
|
}, W );
|
||||||
|
this.__comp( kCode, function(){
|
||||||
|
debug.Info( "Bracket boundary [" );
|
||||||
|
}, S_BRACKET_L );
|
||||||
|
this.__comp( kCode, function(){
|
||||||
|
debug.Info( "Bracket boundary ]" );
|
||||||
|
}, S_BRACKET_R );
|
||||||
|
this.__comp( kCode, function(){
|
||||||
|
debug.Info( "Bracket boundary {" );
|
||||||
|
}, SHIFT + S_BRACKET_L );
|
||||||
|
this.__comp( kCode, function(){
|
||||||
|
debug.Info( "Bracket boundary }" );
|
||||||
|
}, SHIFT + S_BRACKET_R );
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sender @param {Components.Vim.VimArea}
|
||||||
|
* e @param {Components.Vim.Controls.InputEvent}
|
||||||
|
* */
|
||||||
|
Controls.prototype.handler = function( sender, e )
|
||||||
|
{
|
||||||
|
// Never capture these keys
|
||||||
|
if( e.keyCode == ( ALT + D )
|
||||||
|
// F2 - F12
|
||||||
|
|| ( F1 < e.keyCode && e.keyCode <= F12 )
|
||||||
|
) return;
|
||||||
|
|
||||||
|
// Clear composite command
|
||||||
|
if( e.Escape && this.__compReg )
|
||||||
|
{
|
||||||
|
this.__compReg = null;
|
||||||
|
this.__cMovement = false;
|
||||||
|
beep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfeeder = this.__cfeeder;
|
||||||
|
var ccur = this.__ccur;
|
||||||
|
|
||||||
|
var kCode = e.keyCode;
|
||||||
|
|
||||||
|
// Action commands are handled by the actions themselves
|
||||||
|
if( ccur.action )
|
||||||
|
{
|
||||||
|
if( e.Escape )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
ccur.closeAction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( ccur.action.allowMovement )
|
||||||
|
this.__cursorCommand( e, kCode );
|
||||||
|
|
||||||
|
if( ccur.action.handler( e ) )
|
||||||
|
{
|
||||||
|
ccur.closeAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if( this.__cursorCommand( e ) ) return;
|
||||||
|
if( this.__actionCommand( e ) ) return;
|
||||||
|
};
|
||||||
|
|
||||||
|
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.altKey ? ALT : 0 );
|
||||||
|
|
||||||
|
this.__modKeys = c == KEY_SHIFT || c == KEY_CTRL || c == KEY_ALT;
|
||||||
|
this.__key = e.key;
|
||||||
|
};
|
||||||
|
|
||||||
|
__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; } );
|
||||||
|
|
||||||
|
InputEvent.prototype.kMap = function( map )
|
||||||
|
{
|
||||||
|
return this.__kCode == Map( map );
|
||||||
|
};
|
||||||
|
|
||||||
|
InputEvent.prototype.preventDefault = function()
|
||||||
|
{
|
||||||
|
if( this.__e ) this.__e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
ns[ NS_EXPORT ]( EX_CLASS, "Controls", Controls );
|
ns[ NS_EXPORT ]( EX_CLASS, "Controls", Controls );
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "InputEvent", InputEvent );
|
||||||
})();
|
})();
|
||||||
|
@ -9,26 +9,6 @@
|
|||||||
|
|
||||||
var Actions = __import( "Components.Vim.Actions.*" );
|
var Actions = __import( "Components.Vim.Actions.*" );
|
||||||
|
|
||||||
var GetLine = function( buffs, l )
|
|
||||||
{
|
|
||||||
/** @type {Components.Vim.LineBuffer} */
|
|
||||||
var LineHead = buffs[0];
|
|
||||||
l ++;
|
|
||||||
|
|
||||||
for( var i = 0, line = LineHead;
|
|
||||||
line && i < l; i ++ )
|
|
||||||
{
|
|
||||||
LineHead = line;
|
|
||||||
while( line )
|
|
||||||
{
|
|
||||||
line = line.next;
|
|
||||||
if( line.br ) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return LineHead;
|
|
||||||
};
|
|
||||||
|
|
||||||
var LineOffset = function( buffs, l )
|
var LineOffset = function( buffs, l )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.LineBuffer} */
|
/** @type {Components.Vim.LineBuffer} */
|
||||||
@ -55,6 +35,25 @@
|
|||||||
return offset;
|
return offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Rush cursor to wanted position "d" then get the actual position
|
||||||
|
var GetRushPos = function( c, d )
|
||||||
|
{
|
||||||
|
var line = c.getLine();
|
||||||
|
var l = c.Y + d;
|
||||||
|
var i = c.Y;
|
||||||
|
|
||||||
|
// First line ( visual ) does not count
|
||||||
|
if( line != c.feeder.firstBuffer ) i --;
|
||||||
|
|
||||||
|
for( ; i < l; line = line.nextLine )
|
||||||
|
{
|
||||||
|
if( line.placeholder ) break;
|
||||||
|
if( line.br ) i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
var Cursor = function( feeder )
|
var Cursor = function( feeder )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.LineFeeder} */
|
/** @type {Components.Vim.LineFeeder} */
|
||||||
@ -72,14 +71,23 @@
|
|||||||
this.Y = 0;
|
this.Y = 0;
|
||||||
|
|
||||||
// The resulting position
|
// The resulting position
|
||||||
this.P = 0;
|
this.PStart = 0;
|
||||||
|
this.PEnd = 1;
|
||||||
|
|
||||||
// State recorder
|
// State recorder
|
||||||
this.rec = new Recorder();
|
this.rec = new Recorder();
|
||||||
|
|
||||||
this.action = null;
|
this.action = null;
|
||||||
|
|
||||||
|
this.blink = true;
|
||||||
|
this.pSpace = false;
|
||||||
|
|
||||||
|
this.__suppEvt = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set by VimArea
|
||||||
|
Cursor.prototype.Vim;
|
||||||
|
|
||||||
// Can only be 1, -1
|
// Can only be 1, -1
|
||||||
// 0 will be treated as undefined
|
// 0 will be treated as undefined
|
||||||
Cursor.prototype.moveX = function( d, penentrate, phantomSpace )
|
Cursor.prototype.moveX = function( d, penentrate, phantomSpace )
|
||||||
@ -93,15 +101,18 @@
|
|||||||
|
|
||||||
var buffs = this.feeder.lineBuffers;
|
var buffs = this.feeder.lineBuffers;
|
||||||
|
|
||||||
if( penentrate && x < 0 && ( 0 < this.feeder.panY || 0 < this.Y ) )
|
if( penentrate )
|
||||||
{
|
{
|
||||||
this.moveY( -1 );
|
if( x < 0 && ( 0 < this.feeder.panY || 0 < this.Y ) )
|
||||||
this.lineEnd( phantomSpace );
|
{
|
||||||
return;
|
this.moveY( -1 );
|
||||||
|
this.lineEnd( phantomSpace );
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {Components.Vim.LineBuffer} */
|
/** @type {Components.Vim.LineBuffer} */
|
||||||
var line = GetLine( buffs, this.Y );
|
var line = this.getLine();
|
||||||
var content = line.visualLines.join( "\n" );
|
var content = line.visualLines.join( "\n" );
|
||||||
var cLen = content.length;
|
var cLen = content.length;
|
||||||
|
|
||||||
@ -110,12 +121,12 @@
|
|||||||
// Include empty lines befor cursor end
|
// Include empty lines befor cursor end
|
||||||
if( ( phantomSpace && cLen - 1 <= x ) || ( cLen == 1 && c == undefined ) )
|
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
|
// ( 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" )
|
else if( c == "\n" )
|
||||||
{
|
{
|
||||||
@ -145,58 +156,98 @@
|
|||||||
|
|
||||||
Cursor.prototype.updatePosition = function()
|
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.__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" ) );
|
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
};
|
};
|
||||||
|
|
||||||
Cursor.prototype.moveY = function( d, penentrate )
|
Cursor.prototype.moveY = function( d, penentrate )
|
||||||
{
|
{
|
||||||
|
var i;
|
||||||
var Y = this.Y + d;
|
var Y = this.Y + d;
|
||||||
|
var feeder = this.feeder;
|
||||||
var line;
|
var line;
|
||||||
|
|
||||||
if( Y < 0 )
|
if( Y < 0 )
|
||||||
{
|
{
|
||||||
this.feeder.pan( undefined, d );
|
feeder.pan( undefined, d );
|
||||||
|
|
||||||
this.Y = 0;
|
this.Y = 0;
|
||||||
this.moveX();
|
this.moveX();
|
||||||
this.updatePosition();
|
this.updatePosition();
|
||||||
|
|
||||||
this.feeder.softReset();
|
feeder.softReset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if( this.feeder.moreAt < Y )
|
// More at bottom, start panning
|
||||||
|
else if( !feeder.EOF && feeder.moreAt < Y )
|
||||||
{
|
{
|
||||||
var feeder = this.feeder;
|
var feeder = this.feeder;
|
||||||
var lastLine = feeder.lastBuffer.lineNum;
|
|
||||||
var lineShift = Y - feeder.moreAt;
|
|
||||||
|
|
||||||
var i = 0;
|
if( penentrate )
|
||||||
while( !feeder.EOF )
|
|
||||||
{
|
{
|
||||||
feeder.pan( undefined, lineShift + i );
|
feeder.pan( undefined, Y - moreAt );
|
||||||
|
}
|
||||||
|
else if( feeder.linesTotal < Y )
|
||||||
|
{
|
||||||
|
while( !feeder.EOF )
|
||||||
|
{
|
||||||
|
feeder.pan( undefined, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
i = GetRushPos( this, d );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var lastLine = feeder.lastBuffer.lineNum;
|
||||||
|
var lineShift = Y - feeder.moreAt;
|
||||||
|
var thisLine = this.getLine().lineNum;
|
||||||
|
|
||||||
|
if( !feeder.EOF )
|
||||||
|
feeder.pan( undefined, lineShift );
|
||||||
|
|
||||||
// if it turns out to be the same line
|
// if it turns out to be the same line
|
||||||
// before after panning
|
// before after panning
|
||||||
// we keep scrolling it ( panning )
|
// we keep scrolling it ( panning )
|
||||||
// until the entire line cosumes the screen
|
// until the entire line cosumes the screen
|
||||||
if( feeder.lastBuffer.lineNum == lastLine )
|
while( !feeder.EOF && feeder.lastBuffer.lineNum == lastLine )
|
||||||
{
|
{
|
||||||
i ++;
|
feeder.pan( undefined, 1 );
|
||||||
}
|
}
|
||||||
else break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The line number cursor need to be in
|
// The line number cursor need to be in
|
||||||
Y = lastLine + lineShift;
|
Y = thisLine + d;
|
||||||
|
|
||||||
// Calculate the visual line position
|
i = this.Y;
|
||||||
for( i = 0, line = feeder.firstBuffer;
|
this.Y = 0;
|
||||||
line != feeder.lastBuffer;
|
// Calculate the visual line position "i"
|
||||||
line = line.next )
|
for( var line = this.getLine();
|
||||||
{
|
line && line.lineNum != Y && !line.placeholder;
|
||||||
if( line.br ) i ++;
|
this.Y ++, line = this.getLine() )
|
||||||
if( line.lineNum == Y || line.next.placeholder ) break;
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
i = this.Y;
|
||||||
|
|
||||||
|
// Check if this line is collapsed
|
||||||
|
if( !feeder.EOF && feeder.lastBuffer.next.lineNum == line.lineNum )
|
||||||
|
{
|
||||||
|
// If yes, step back to last visible line
|
||||||
|
i --;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Y = i;
|
this.Y = i;
|
||||||
@ -204,20 +255,18 @@
|
|||||||
this.moveX();
|
this.moveX();
|
||||||
this.updatePosition();
|
this.updatePosition();
|
||||||
|
|
||||||
|
// Because it is panned, soft reset is needed
|
||||||
feeder.softReset();
|
feeder.softReset();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if ( 0 < d )
|
else if ( 0 < d )
|
||||||
{
|
{
|
||||||
// If panning is forward
|
var line = this.getLine();
|
||||||
// and next line does not exists
|
// If already at bottom
|
||||||
line = this.getLine().nextLine;
|
if( line.nextLine.placeholder ) return;
|
||||||
if( !line || line.placeholder )
|
|
||||||
{
|
Y = GetRushPos( this, d );
|
||||||
// do nothing
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Y = Y;
|
this.Y = Y;
|
||||||
@ -226,25 +275,28 @@
|
|||||||
this.updatePosition();
|
this.updatePosition();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Open an action handler
|
||||||
|
// i.e. YANK, VISUAL, INSERT, UNDO, etc.
|
||||||
Cursor.prototype.openAction = function( name )
|
Cursor.prototype.openAction = function( name )
|
||||||
{
|
{
|
||||||
if( this.action ) this.action.dispose();
|
if( this.action ) this.action.dispose();
|
||||||
this.action = new (Actions[ name ])( this );
|
this.action = new (Actions[ name ])( this );
|
||||||
this.__pulseMsg = null;
|
this.__pulseMsg = null;
|
||||||
|
|
||||||
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
this.__fireUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
Cursor.prototype.closeAction = function()
|
Cursor.prototype.closeAction = function()
|
||||||
{
|
{
|
||||||
if( !this.action ) return;
|
if( !this.action ) return;
|
||||||
this.action.dispose();
|
this.action.dispose();
|
||||||
|
this.__pulseMsg = this.action.getMessage();
|
||||||
this.action = null;
|
this.action = null;
|
||||||
this.__pulseMsg = null;
|
|
||||||
|
|
||||||
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
this.__fireUpdate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Open, Run, then close an action
|
||||||
Cursor.prototype.openRunAction = function( name, e )
|
Cursor.prototype.openRunAction = function( name, e )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.IAction} */
|
/** @type {Components.Vim.IAction} */
|
||||||
@ -253,22 +305,26 @@
|
|||||||
this.__pulseMsg = action.getMessage();
|
this.__pulseMsg = action.getMessage();
|
||||||
action.dispose();
|
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()
|
Cursor.prototype.getLine = function()
|
||||||
{
|
{
|
||||||
var feeder = this.feeder;
|
var feeder = this.feeder;
|
||||||
var line = feeder.firstBuffer;
|
var line = feeder.firstBuffer;
|
||||||
|
var eBuffer = feeder.lastBuffer.next;
|
||||||
for( var i = 0;
|
for( var i = 0;
|
||||||
line != feeder.lastBuffer;
|
line != eBuffer;
|
||||||
line = line.next )
|
line = line.next )
|
||||||
{
|
{
|
||||||
if( line.br ) i ++;
|
if( line.br ) i ++;
|
||||||
if( this.Y == i ) break;
|
if( this.Y == i ) return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
return line;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The absX for current Line
|
// The absX for current Line
|
||||||
@ -356,8 +412,8 @@
|
|||||||
__readOnly( Cursor.prototype, "position", function()
|
__readOnly( Cursor.prototype, "position", function()
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
start: this.P
|
start: this.PStart
|
||||||
, end: this.P + 1
|
, end: this.PEnd
|
||||||
};
|
};
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
/** @type {Components.Vim.Cursor} */
|
/** @type {Components.Vim.Cursor} */
|
||||||
var Cursor = ns[ NS_INVOKE ]( "Cursor" );
|
var Cursor = ns[ NS_INVOKE ]( "Cursor" );
|
||||||
|
|
||||||
|
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
||||||
|
|
||||||
var Feeder = function( rows, cols )
|
var Feeder = function( rows, cols )
|
||||||
{
|
{
|
||||||
var lineBuffers = [];
|
var lineBuffers = [];
|
||||||
@ -92,7 +94,7 @@
|
|||||||
this.__softRender = function()
|
this.__softRender = function()
|
||||||
{
|
{
|
||||||
var line = _self.lineBuffers[ _self.__rStart ];
|
var line = _self.lineBuffers[ _self.__rStart ];
|
||||||
var steps = _self.__rLength;
|
var steps = _self.__rLength + 1;
|
||||||
|
|
||||||
for( var i = 0;
|
for( var i = 0;
|
||||||
line && i < steps && ( line = line.next ) && placeholdCond( line );
|
line && i < steps && ( line = line.next ) && placeholdCond( line );
|
||||||
@ -170,7 +172,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
__readOnly( Feeder.prototype, "linesTotal", function() {
|
__readOnly( Feeder.prototype, "linesTotal", function() {
|
||||||
return this.content.match( "\n" );
|
return occurence( this.content, "\n" );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
__readOnly( Feeder.prototype, "firstBuffer", function() {
|
__readOnly( Feeder.prototype, "firstBuffer", function() {
|
||||||
|
50
botanjs/src/Components/Vim/State/Registers.js
Normal file
50
botanjs/src/Components/Vim/State/Registers.js
Normal file
@ -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 );
|
||||||
|
})();
|
71
botanjs/src/Components/Vim/State/Stator.js
Normal file
71
botanjs/src/Components/Vim/State/Stator.js
Normal file
@ -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 );
|
||||||
|
})();
|
@ -10,14 +10,20 @@
|
|||||||
/** @type {System.Debug} */
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.State.Registers} */
|
||||||
|
var Registers = __import( "Components.Vim.State.Registers" );
|
||||||
|
|
||||||
/** @type {Components.Vim.LineFeeder} */
|
/** @type {Components.Vim.LineFeeder} */
|
||||||
var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
|
var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
|
||||||
/** @type {Components.Vim.StatusBar} */
|
/** @type {Components.Vim.StatusBar} */
|
||||||
var StatusBar = ns[ NS_INVOKE ]( "StatusBar" );
|
var StatusBar = ns[ NS_INVOKE ]( "StatusBar" );
|
||||||
|
|
||||||
var VimControls = ns[ NS_INVOKE ]( "Controls" );
|
var VimControls = ns[ NS_INVOKE ]( "Controls" );
|
||||||
|
var InputEvent = ns[ NS_INVOKE ]( "InputEvent" );
|
||||||
var mesg = ns[ NS_INVOKE ]( "Message" );
|
var mesg = ns[ NS_INVOKE ]( "Message" );
|
||||||
|
|
||||||
|
var Insts = [];
|
||||||
|
|
||||||
var KeyHandler = function( sender, handler )
|
var KeyHandler = function( sender, handler )
|
||||||
{
|
{
|
||||||
return function( e )
|
return function( e )
|
||||||
@ -26,7 +32,7 @@
|
|||||||
if ( e.keyCode ) code = e.keyCode;
|
if ( e.keyCode ) code = e.keyCode;
|
||||||
else if ( e.which ) code = e.which;
|
else if ( e.which ) code = e.which;
|
||||||
|
|
||||||
handler( sender, e );
|
handler( sender, new InputEvent( sender, e ) );
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,17 +59,14 @@
|
|||||||
|
|
||||||
var _self = this;
|
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( "Focus", function() { _self.__active = true; } );
|
||||||
stage.addEventListener( "Blur", function() { _self.__active = false; } );
|
stage.addEventListener( "Blur", function() { _self.__active = false; } );
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
this.VisualizeVimFrame( element.value );
|
this.VisualizeVimFrame( element.value );
|
||||||
|
|
||||||
|
// Push this instance
|
||||||
|
Insts.push( this );
|
||||||
};
|
};
|
||||||
|
|
||||||
VimArea.prototype.select = function( sel )
|
VimArea.prototype.select = function( sel )
|
||||||
@ -92,25 +95,24 @@
|
|||||||
// Content feeder
|
// Content feeder
|
||||||
var cfeeder = new LineFeeder( cRange, c );
|
var cfeeder = new LineFeeder( cRange, c );
|
||||||
|
|
||||||
cfeeder.init( content );
|
// 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" );
|
||||||
|
|
||||||
// Status can consumes up to full screen, I think
|
// Status can consumes up to full screen, I think
|
||||||
sfeeder = new LineFeeder( r, c );
|
sfeeder = new LineFeeder( r, c );
|
||||||
sfeeder.setRender( false );
|
sfeeder.setRender( false );
|
||||||
|
|
||||||
// XXX: Placeholder
|
// Set the Vim instance
|
||||||
|
cfeeder.cursor.Vim = this;
|
||||||
|
sfeeder.cursor.Vim = this;
|
||||||
|
|
||||||
|
// Set the stamps
|
||||||
var statusBar = new StatusBar( c );
|
var statusBar = new StatusBar( c );
|
||||||
statusBar.stamp( -18, function(){
|
statusBar.stamp( -18, function(){ return cfeeder.lineStat; } );
|
||||||
return cfeeder.lineStat;
|
statusBar.stamp( -3, function(){ return mesg( cfeeder.docPos ); } );
|
||||||
});
|
statusBar.stamp( 0, function(){ return cfeeder.cursor.message; } );
|
||||||
|
|
||||||
statusBar.stamp( -3, function(){
|
|
||||||
return mesg( cfeeder.docPos );
|
|
||||||
} );
|
|
||||||
|
|
||||||
statusBar.stamp( 0, function(){
|
|
||||||
return cfeeder.cursor.message;
|
|
||||||
} );
|
|
||||||
|
|
||||||
sfeeder.init( statusBar.statusText );
|
sfeeder.init( statusBar.statusText );
|
||||||
|
|
||||||
@ -132,6 +134,7 @@
|
|||||||
this.contentFeeder = cfeeder;
|
this.contentFeeder = cfeeder;
|
||||||
this.statusFeeder = sfeeder;
|
this.statusFeeder = sfeeder;
|
||||||
this.statusBar = statusBar;
|
this.statusBar = statusBar;
|
||||||
|
this.registers = new Registers();
|
||||||
|
|
||||||
this.__cursor = cfeeder.cursor;
|
this.__cursor = cfeeder.cursor;
|
||||||
|
|
||||||
@ -139,15 +142,25 @@
|
|||||||
Cycle.perma( "VimCursorBlinkCycle" + element.id, function()
|
Cycle.perma( "VimCursorBlinkCycle" + element.id, function()
|
||||||
{
|
{
|
||||||
_self.select(
|
_self.select(
|
||||||
( _self.__blink = !_self.__blink )
|
!_self.__cursor.blink || ( _self.__blink = !_self.__blink )
|
||||||
? _self.__cursor.position
|
? _self.__cursor.position
|
||||||
: { start: 0, end: 0 }
|
: { start: 0, end: 0 }
|
||||||
);
|
);
|
||||||
}, 600 );
|
}, 600 );
|
||||||
|
|
||||||
|
var controls = new VimControls( this );
|
||||||
|
this.stage.addEventListener(
|
||||||
|
"KeyDown"
|
||||||
|
, KeyHandler( this, controls.handler.bind( controls ) )
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
__readOnly( VimArea, "Instances", function() {
|
||||||
|
return Insts.slice();
|
||||||
|
} );
|
||||||
|
|
||||||
__readOnly( VimArea.prototype, "content", function() {
|
__readOnly( VimArea.prototype, "content", function() {
|
||||||
return this.contentFeeder.content;
|
return this.contentFeeder.content.slice( 0, -1 );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea );
|
ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea );
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
"INSERT": "-- INSERT --"
|
"INSERT": "-- INSERT --"
|
||||||
, "REPLACE": "-- REPLACE --"
|
, "REPLACE": "-- REPLACE --"
|
||||||
, "MORE": "-- MORE --"
|
, "MORE": "-- MORE --"
|
||||||
|
, "VISUAL": "-- VISUAL --"
|
||||||
, "VISLINE": "-- VISUAL LINE --"
|
, "VISLINE": "-- VISUAL LINE --"
|
||||||
, "WRITE": "\"%1\" %2L, %3C written"
|
, "WRITE": "\"%1\" %2L, %3C written"
|
||||||
, "CONTINUE": "Press ENTER or type command to continue"
|
, "CONTINUE": "Press ENTER or type command to continue"
|
||||||
@ -16,6 +17,8 @@
|
|||||||
|
|
||||||
, "UNDO_LIMIT": "Already at oldest change"
|
, "UNDO_LIMIT": "Already at oldest change"
|
||||||
, "REDO_LIMIT": "Already at newest change"
|
, "REDO_LIMIT": "Already at newest change"
|
||||||
|
|
||||||
|
, "LINE_FEWER": "%1 fewer lines"
|
||||||
};
|
};
|
||||||
|
|
||||||
var errors = {
|
var errors = {
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
Log.writeLine( e.name + "\n\t" + e.message + "\n\t" + e.stack, Log.ERROR );
|
Log.writeLine( e.name + "\n\t" + e.message + "\n\t" + e.stack, Log.ERROR );
|
||||||
};
|
};
|
||||||
|
|
||||||
var Info = function(e)
|
var Info = function()
|
||||||
{
|
{
|
||||||
if( st_info )
|
if( st_info )
|
||||||
Log.writeLine( e, Log.INFO );
|
Log.writeLine( Array.prototype.join.call( arguments, " " ), Log.INFO );
|
||||||
};
|
};
|
||||||
|
|
||||||
var turnOff = function( what )
|
var turnOff = function( what )
|
||||||
|
15
botanjs/src/externs/Components.Vim.Controls.InputEvent.js
Normal file
15
botanjs/src/externs/Components.Vim.Controls.InputEvent.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/** @constructor */
|
||||||
|
Components.Vim.Controls.InputEvent = function(){};
|
||||||
|
|
||||||
|
/** @type {Components.Vim.VimArea} */
|
||||||
|
Components.Vim.Controls.InputEvent.target;
|
||||||
|
/** @type String */
|
||||||
|
Components.Vim.Controls.InputEvent.key;
|
||||||
|
/** @type Boolean */
|
||||||
|
Components.Vim.Controls.InputEvent.ModKeys;
|
||||||
|
/** @type Boolean */
|
||||||
|
Components.Vim.Controls.InputEvent.Escape;
|
||||||
|
/** @type Number */
|
||||||
|
Components.Vim.Controls.InputEvent.keyCode;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.Controls.InputEvent.kMap;
|
2
botanjs/src/externs/Components.Vim.Controls.js
Normal file
2
botanjs/src/externs/Components.Vim.Controls.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/** @constructor */
|
||||||
|
Components.Vim.Controls = function(){};
|
@ -1,6 +1,8 @@
|
|||||||
/** @constructor */
|
/** @constructor */
|
||||||
Components.Vim.Cursor = function(){};
|
Components.Vim.Cursor = function(){};
|
||||||
|
|
||||||
|
/** @type {Components.Vim.VimArea} */
|
||||||
|
Components.Vim.Cursor.Vim;
|
||||||
/** @type {Components.Vim.LineFeeder} */
|
/** @type {Components.Vim.LineFeeder} */
|
||||||
Components.Vim.Cursor.feeder;
|
Components.Vim.Cursor.feeder;
|
||||||
/** @type {Components.Vim.IAction} */
|
/** @type {Components.Vim.IAction} */
|
||||||
@ -24,13 +26,23 @@ Components.Vim.Cursor.openAction;
|
|||||||
Components.Vim.Cursor.openRunAction;
|
Components.Vim.Cursor.openRunAction;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.Cursor.closeAction;
|
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} */
|
/** @type {Array} */
|
||||||
Components.Vim.Cursor.lineBuffers;
|
Components.Vim.Cursor.lineBuffers;
|
||||||
/** @type Number */
|
/** @type Number */
|
||||||
Components.Vim.Cursor.pX;
|
Components.Vim.Cursor.pX;
|
||||||
/** @type Number */
|
/** @type Number */
|
||||||
Components.Vim.Cursor.P;
|
Components.Vim.Cursor.PStart;
|
||||||
|
/** @type Number */
|
||||||
|
Components.Vim.Cursor.PEnd;
|
||||||
/** @type Number */
|
/** @type Number */
|
||||||
Components.Vim.Cursor.aX;
|
Components.Vim.Cursor.aX;
|
||||||
/** @type Number */
|
/** @type Number */
|
||||||
|
@ -7,3 +7,6 @@ Components.Vim.IAction.dispose;
|
|||||||
Components.Vim.IAction.handler;
|
Components.Vim.IAction.handler;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.IAction.getMessage;
|
Components.Vim.IAction.getMessage;
|
||||||
|
|
||||||
|
/** @type Boolean */
|
||||||
|
Components.Vim.IAction.allowMovement;
|
||||||
|
@ -37,6 +37,8 @@ Components.Vim.LineFeeder.panY;
|
|||||||
/** @type Number */
|
/** @type Number */
|
||||||
Components.Vim.LineFeeder.moreAt;
|
Components.Vim.LineFeeder.moreAt;
|
||||||
/** @type Number */
|
/** @type Number */
|
||||||
|
Components.Vim.LineFeeder.linesTotal;
|
||||||
|
/** @type Number */
|
||||||
Components.Vim.LineFeeder.linesOccupied;
|
Components.Vim.LineFeeder.linesOccupied;
|
||||||
/** @type String */
|
/** @type String */
|
||||||
Components.Vim.LineFeeder.docPos;
|
Components.Vim.LineFeeder.docPos;
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
Components.Vim.State.Recorder = function(){};
|
Components.Vim.State.Recorder = function(){};
|
||||||
|
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.State.undo;
|
Components.Vim.State.Recorder.undo;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.State.redo;
|
Components.Vim.State.Recorder.redo;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.State.record;
|
Components.Vim.State.Recorder.record;
|
||||||
|
9
botanjs/src/externs/Components.Vim.State.Registers.js
Normal file
9
botanjs/src/externs/Components.Vim.State.Registers.js
Normal file
@ -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;
|
@ -12,3 +12,5 @@ Components.Vim.VimArea.statusBar;
|
|||||||
Components.Vim.VimArea.rows;
|
Components.Vim.VimArea.rows;
|
||||||
/** @type {Number} */
|
/** @type {Number} */
|
||||||
Components.Vim.VimArea.cols;
|
Components.Vim.VimArea.cols;
|
||||||
|
/** @type {Array} */
|
||||||
|
Components.Vim.VimArea.Instances;
|
||||||
|
Loading…
Reference in New Issue
Block a user