forked from Botanical/BotanJS
Merge remote-tracking branch 'vim/master' into Astro
This commit is contained in:
commit
dd12efa607
@ -10,6 +10,7 @@
|
|||||||
var Stack = __import( "Components.Vim.State.Stack" );
|
var Stack = __import( "Components.Vim.State.Stack" );
|
||||||
|
|
||||||
var Mesg = __import( "Components.Vim.Message" );
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
var beep = __import( "Components.Vim.Beep" );
|
||||||
|
|
||||||
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
||||||
|
|
||||||
@ -20,19 +21,23 @@
|
|||||||
this.__cursor = Cursor;
|
this.__cursor = Cursor;
|
||||||
this.__nline = 0;
|
this.__nline = 0;
|
||||||
this.__startX = Cursor.aPos;
|
this.__startX = Cursor.aPos;
|
||||||
|
this.__panY = this.__cursor.feeder.panY;
|
||||||
|
|
||||||
|
Cursor.suppressEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
DELETE.prototype.allowMovement = true;
|
DELETE.prototype.allowMovement = true;
|
||||||
|
|
||||||
DELETE.prototype.dispose = function()
|
DELETE.prototype.dispose = function()
|
||||||
{
|
{
|
||||||
|
this.__cursor.unsuppressEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
DELETE.prototype.handler = function( e, sp )
|
DELETE.prototype.handler = function( e, sp )
|
||||||
{
|
{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
if( e.ModKeys ) return;
|
||||||
|
|
||||||
/** @type {Components.Vim.State.Registers} */
|
/** @type {Components.Vim.State.Registers} */
|
||||||
var reg = e.target.registers;
|
var reg = e.target.registers;
|
||||||
@ -41,21 +46,93 @@
|
|||||||
var feeder = cur.feeder;
|
var feeder = cur.feeder;
|
||||||
|
|
||||||
var Triggered = false;
|
var Triggered = false;
|
||||||
|
var newLine = false;
|
||||||
|
|
||||||
if( sp == undefined )
|
if( sp == undefined )
|
||||||
{
|
{
|
||||||
if( this.__startX != cur.aPos )
|
Triggered = true;
|
||||||
{
|
|
||||||
Triggered = true;
|
|
||||||
|
|
||||||
if( e.kMap( "l" ) )
|
sp = this.__startX;
|
||||||
|
|
||||||
|
var currAp = cur.aPos;
|
||||||
|
if( this.__startX != currAp )
|
||||||
|
{
|
||||||
|
// Remove to start
|
||||||
|
if( e.kMap( "^" ) )
|
||||||
|
{
|
||||||
|
sp --;
|
||||||
|
}
|
||||||
|
// Remove char in cursor
|
||||||
|
else if( e.kMap( "l" ) )
|
||||||
{
|
{
|
||||||
cur.moveX( -1 );
|
cur.moveX( -1 );
|
||||||
}
|
}
|
||||||
|
// Remove char before cursor
|
||||||
sp = this.__startX;
|
else if( e.kMap( "h" ) )
|
||||||
|
{
|
||||||
|
sp = currAp;
|
||||||
|
}
|
||||||
|
// Remove the current and the following line
|
||||||
|
else if( e.kMap( "j" ) )
|
||||||
|
{
|
||||||
|
newLine = true;
|
||||||
|
cur.lineEnd( true );
|
||||||
|
sp = cur.aPos;
|
||||||
|
cur.moveY( -1 );
|
||||||
|
cur.lineStart();
|
||||||
|
this.__startX = cur.aPos;
|
||||||
|
}
|
||||||
|
// Remove the current and the preceding line
|
||||||
|
else if( e.kMap( "k" ) )
|
||||||
|
{
|
||||||
|
newLine = true;
|
||||||
|
cur.moveY( 1 );
|
||||||
|
cur.lineEnd( true );
|
||||||
|
sp = cur.aPos;
|
||||||
|
cur.moveY( -1 );
|
||||||
|
cur.lineStart();
|
||||||
|
}
|
||||||
|
else if( this.__startX < currAp )
|
||||||
|
{
|
||||||
|
// Swap the movement
|
||||||
|
// This is to move the REDO / UNDO Cursor
|
||||||
|
// position to the earlier position
|
||||||
|
sp = currAp;
|
||||||
|
cur.moveTo( this.__startX );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the current line
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( e.kMap( "d" ) )
|
||||||
|
{
|
||||||
|
newLine = true;
|
||||||
|
cur.lineEnd( true );
|
||||||
|
sp = cur.aPos;
|
||||||
|
cur.lineStart();
|
||||||
|
}
|
||||||
|
else if( e.range )
|
||||||
|
{
|
||||||
|
sp = e.range.close;
|
||||||
|
cur.moveTo( e.range.open, true );
|
||||||
|
}
|
||||||
|
else if( e.kMap( "^" ) )
|
||||||
|
{
|
||||||
|
// Do nothing as nothing can be removed
|
||||||
|
// since there is no successful movement
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// this is the same as kMap( "h" ) above
|
||||||
|
else if( e.kMap( "$" ) )
|
||||||
|
{
|
||||||
|
sp = cur.aPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var c = feeder.content;
|
var c = feeder.content;
|
||||||
@ -70,23 +147,23 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var removed = c.substring( s, e + 1 );
|
var removed = c.substring( s, e + 1 );
|
||||||
reg.change( removed );
|
reg.change( removed, newLine );
|
||||||
|
|
||||||
this.__nline = occurence( removed, "\n" );
|
this.__nline = occurence( removed, "\n" );
|
||||||
|
|
||||||
feeder.content = c.substring( 0, s ) + c.substring( e + 1 );
|
feeder.content = c.substring( 0, s ) + c.substring( e + 1 );
|
||||||
|
|
||||||
|
// Try to keep the original panning if possible
|
||||||
|
feeder.pan( undefined
|
||||||
|
, this.__panY < feeder.panY
|
||||||
|
? this.__panY - feeder.panY
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
cur.moveTo( s );
|
||||||
|
|
||||||
var stator = new Stator( cur, s );
|
var stator = new Stator( cur, s );
|
||||||
var stack = new Stack();
|
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 );
|
var f = stator.save( 0, removed );
|
||||||
stack.store( function() {
|
stack.store( function() {
|
||||||
f();
|
f();
|
||||||
@ -96,8 +173,6 @@
|
|||||||
|
|
||||||
cur.rec.record( stack );
|
cur.rec.record( stack );
|
||||||
|
|
||||||
feeder.pan();
|
|
||||||
|
|
||||||
return Triggered;
|
return Triggered;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,7 +180,7 @@
|
|||||||
{
|
{
|
||||||
if( this.__nline )
|
if( this.__nline )
|
||||||
{
|
{
|
||||||
return Mesg( "LINE_FEWER", this.__nline );
|
return Mesg( "LINES_FEWER", this.__nline );
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
|
127
botanjs/src/Components/Vim/Actions/FIND.js
Normal file
127
botanjs/src/Components/Vim/Actions/FIND.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
|
/** @type {System.Debug} */
|
||||||
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
|
||||||
|
// Private static
|
||||||
|
var PATTERN = "";
|
||||||
|
|
||||||
|
var ParsePattern = function( pattern )
|
||||||
|
{
|
||||||
|
var parsed = "";
|
||||||
|
var l = pattern.length;
|
||||||
|
|
||||||
|
for( var i = 1; i < l; i ++ )
|
||||||
|
{
|
||||||
|
switch( pattern[ i ] )
|
||||||
|
{
|
||||||
|
case "^I":
|
||||||
|
parsed += "\t";
|
||||||
|
break;
|
||||||
|
case "\\":
|
||||||
|
var tok = pattern[ ++ i ];
|
||||||
|
debug.Error( "Unknown escaped token: " + tok );
|
||||||
|
++ i;
|
||||||
|
default:
|
||||||
|
parsed += pattern[ i ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var RegEx = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var RegEx = new RegExp( parsed, "gm" );
|
||||||
|
}
|
||||||
|
catch( ex )
|
||||||
|
{
|
||||||
|
debug.Error( ex );
|
||||||
|
}
|
||||||
|
|
||||||
|
return RegEx;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {Components.Vim.Cursor.IAction} */
|
||||||
|
var FIND = function( Cursor )
|
||||||
|
{
|
||||||
|
/** @type {Components.Vim.Cursor} */
|
||||||
|
this.__cursor = Cursor;
|
||||||
|
this.__msg = "";
|
||||||
|
Cursor.suppressEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
FIND.prototype.dispose = function()
|
||||||
|
{
|
||||||
|
this.__cursor.unsuppressEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
FIND.prototype.handler = function( e, p )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if( p ) PATTERN = p;
|
||||||
|
|
||||||
|
var search = ParsePattern( PATTERN );
|
||||||
|
|
||||||
|
var content = this.__cursor.feeder.content;
|
||||||
|
|
||||||
|
var cur = this.__cursor;
|
||||||
|
var p = cur.aPos;
|
||||||
|
|
||||||
|
var r;
|
||||||
|
var Hit;
|
||||||
|
var FirstHit;
|
||||||
|
var PrevStack = [];
|
||||||
|
|
||||||
|
while( ( r = search.exec( content ) ) !== null )
|
||||||
|
{
|
||||||
|
if( !FirstHit ) FirstHit = r.index;
|
||||||
|
if( p < r.index )
|
||||||
|
{
|
||||||
|
Hit = r.index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrevStack.push( r.index );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( e.kMap( "N" ) )
|
||||||
|
{
|
||||||
|
Hit = PrevStack[ PrevStack.length - 2 ];
|
||||||
|
if( Hit == undefined )
|
||||||
|
{
|
||||||
|
this.__msg = Mesg( "SEARCH_HIT_TOP" );
|
||||||
|
|
||||||
|
while( ( r = search.exec( content ) ) !== null ) Hit = r.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( FirstHit != undefined && Hit == undefined )
|
||||||
|
{
|
||||||
|
// Search Hit Bottom
|
||||||
|
Hit = FirstHit;
|
||||||
|
this.__msg = Mesg( "SEARCH_HIT_BOTTOM" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.__msg = PATTERN.join( "" )
|
||||||
|
}
|
||||||
|
|
||||||
|
if( Hit == undefined )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur.moveTo( Hit );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FIND.prototype.getMessage = function()
|
||||||
|
{
|
||||||
|
return this.__msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "FIND", FIND );
|
||||||
|
})();
|
@ -29,16 +29,23 @@
|
|||||||
/** @type {Components.Vim.Cursor} */
|
/** @type {Components.Vim.Cursor} */
|
||||||
this.__cursor = Cursor;
|
this.__cursor = Cursor;
|
||||||
|
|
||||||
this.__Stator = new Stator( Cursor );
|
this.__stator = new Stator( Cursor );
|
||||||
|
|
||||||
// Initialize this stack
|
// Initialize this stack
|
||||||
this.__rec( "", true );
|
this.__rec( "", true );
|
||||||
|
|
||||||
|
var l = this.__cursor.feeder.firstBuffer.cols;
|
||||||
|
var msg = Mesg( "INSERT" );
|
||||||
|
|
||||||
|
for( var i = msg.length; i < l; i ++ ) msg += " ";
|
||||||
|
this.__msg = msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
INSERT.prototype.allowMovement = false;
|
INSERT.prototype.allowMovement = false;
|
||||||
|
|
||||||
INSERT.prototype.dispose = function()
|
INSERT.prototype.dispose = function()
|
||||||
{
|
{
|
||||||
|
this.__msg = "";
|
||||||
this.__rec( "", true );
|
this.__rec( "", true );
|
||||||
this.__cursor.moveX( -1 );
|
this.__cursor.moveX( -1 );
|
||||||
};
|
};
|
||||||
@ -55,7 +62,7 @@
|
|||||||
) return;
|
) return;
|
||||||
|
|
||||||
this.__stack.store(
|
this.__stack.store(
|
||||||
this.__Stator.save( this.__insertLength, this.__contentUndo )
|
this.__stator.save( this.__insertLength, this.__contentUndo )
|
||||||
);
|
);
|
||||||
|
|
||||||
this.__cursor.rec.record( this.__stack );
|
this.__cursor.rec.record( this.__stack );
|
||||||
@ -158,11 +165,7 @@
|
|||||||
|
|
||||||
INSERT.prototype.getMessage = function()
|
INSERT.prototype.getMessage = function()
|
||||||
{
|
{
|
||||||
var l = this.__cursor.feeder.firstBuffer.cols;
|
return this.__msg;
|
||||||
var msg = Mesg( "INSERT" );
|
|
||||||
|
|
||||||
for( var i = msg.length; i < l; i ++ ) msg += " ";
|
|
||||||
return msg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ns[ NS_EXPORT ]( EX_CLASS, "INSERT", INSERT );
|
ns[ NS_EXPORT ]( EX_CLASS, "INSERT", INSERT );
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
(function(){
|
(function(){
|
||||||
var ns = __namespace( "Components.Vim.Actions" );
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
/** @type {Components.Vim.State.Stack} */
|
|
||||||
var Stack = __import( "Components.Vim.State.Stack" );
|
|
||||||
/** @type {System.Debug} */
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
101
botanjs/src/Components/Vim/Actions/PUT.js
Normal file
101
botanjs/src/Components/Vim/Actions/PUT.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
|
/** @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 PUT = function( Cursor )
|
||||||
|
{
|
||||||
|
/** @type {Components.Vim.Cursor} */
|
||||||
|
this.__cursor = Cursor;
|
||||||
|
this.__msg = "";
|
||||||
|
Cursor.suppressEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
PUT.prototype.allowMovement = false;
|
||||||
|
|
||||||
|
PUT.prototype.dispose = function()
|
||||||
|
{
|
||||||
|
this.__cursor.unsuppressEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
PUT.prototype.handler = function( e )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// TODO: Get the input for determinating registers
|
||||||
|
var inputStack = false;
|
||||||
|
|
||||||
|
var cput = this.__cursor.Vim.registers.get( inputStack );
|
||||||
|
if( !cput ) return true;
|
||||||
|
|
||||||
|
var clen = cput.length;
|
||||||
|
var nLines = occurence( cput, "\n" );
|
||||||
|
|
||||||
|
var cur = this.__cursor;
|
||||||
|
var feeder = cur.feeder;
|
||||||
|
|
||||||
|
var newLine = cput.newLine;
|
||||||
|
|
||||||
|
// Compensation
|
||||||
|
var c = e.kMap( "P" ) ? 0 : -1;
|
||||||
|
|
||||||
|
if( newLine )
|
||||||
|
{
|
||||||
|
cur.moveY( -c );
|
||||||
|
cur.lineStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
var stator = new Stator( cur );
|
||||||
|
var aP = cur.aPos;
|
||||||
|
|
||||||
|
feeder.content = feeder.content.substring( 0, aP )
|
||||||
|
+ cput
|
||||||
|
+ feeder.content.substring( aP );
|
||||||
|
|
||||||
|
feeder.pan();
|
||||||
|
|
||||||
|
cur.moveTo( 0 < nLines ? aP : aP + clen, true );
|
||||||
|
|
||||||
|
var stack = new Stack();
|
||||||
|
|
||||||
|
if( newLine )
|
||||||
|
{
|
||||||
|
var f = stator.save( clen, "" );
|
||||||
|
stack.store( function()
|
||||||
|
{
|
||||||
|
f();
|
||||||
|
cur.moveY( c );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stack.store( stator.save( clen, "" ) );
|
||||||
|
}
|
||||||
|
cur.rec.record( stack );
|
||||||
|
|
||||||
|
this.__put = cput;
|
||||||
|
|
||||||
|
if( nLines )
|
||||||
|
{
|
||||||
|
this.__msg = Mesg( "LINES_MORE", nLines );
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.moveX( -1 );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
PUT.prototype.getMessage = function()
|
||||||
|
{
|
||||||
|
return this.__msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "PUT", PUT );
|
||||||
|
})();
|
@ -16,7 +16,6 @@
|
|||||||
{
|
{
|
||||||
this.__reset( Cursor );
|
this.__reset( Cursor );
|
||||||
this.__msg = Mesg( "VISUAL" );
|
this.__msg = Mesg( "VISUAL" );
|
||||||
this.__leaveMesg = "";
|
|
||||||
|
|
||||||
Cursor.blink = false;
|
Cursor.blink = false;
|
||||||
Cursor.pSpace = true;
|
Cursor.pSpace = true;
|
||||||
@ -35,11 +34,22 @@
|
|||||||
|
|
||||||
VISUAL.prototype.dispose = function()
|
VISUAL.prototype.dispose = function()
|
||||||
{
|
{
|
||||||
this.__msg = this.__leaveMesg;
|
var c = this.__cursor;
|
||||||
this.__cursor.blink = true;
|
|
||||||
this.__cursor.pSpace = false;
|
c.blink = true;
|
||||||
this.__cursor.PStart = this.__selStart;
|
c.pSpace = false;
|
||||||
this.__cursor.PEnd = this.__selStart + 1;
|
c.PStart = this.__selStart;
|
||||||
|
c.PEnd = this.__selStart + 1;
|
||||||
|
|
||||||
|
// This fix the highlighting position of missing phantomSpace
|
||||||
|
// for maximum filled line
|
||||||
|
if( c.feeder.wrap && 0 < c.X )
|
||||||
|
{
|
||||||
|
c.suppressEvent();
|
||||||
|
c.moveX( -1 );
|
||||||
|
c.moveX( 1 );
|
||||||
|
c.unsuppressEvent();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VISUAL.prototype.handler = function( e, done )
|
VISUAL.prototype.handler = function( e, done )
|
||||||
@ -76,7 +86,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
Action.handler( e, this.__startaP );
|
Action.handler( e, this.__startaP );
|
||||||
this.__leaveMesg = Action.getMessage();
|
|
||||||
|
if( Action.constructor != DELETE )
|
||||||
|
{
|
||||||
|
cur.moveTo( this.__startaP );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__msg = Action.getMessage();
|
||||||
|
|
||||||
Action.dispose();
|
Action.dispose();
|
||||||
cur.unsuppressEvent();
|
cur.unsuppressEvent();
|
||||||
|
@ -1,31 +1,161 @@
|
|||||||
(function(){
|
(function(){
|
||||||
var ns = __namespace( "Components.Vim.Actions" );
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
|
/** @type {System.Debug} */
|
||||||
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
var Mesg = __import( "Components.Vim.Message" );
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
var beep = __import( "Components.Vim.Beep" );
|
||||||
|
|
||||||
|
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
||||||
|
|
||||||
/** @type {Components.Vim.Cursor.IAction} */
|
/** @type {Components.Vim.Cursor.IAction} */
|
||||||
var YANK = function( Cursor )
|
var YANK = function( Cursor )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.Cursor} */
|
/** @type {Components.Vim.Cursor} */
|
||||||
this.__cursor = Cursor;
|
this.__cursor = Cursor;
|
||||||
|
this.__startX = Cursor.aPos;
|
||||||
|
this.__msg = "";
|
||||||
|
|
||||||
|
Cursor.suppressEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
YANK.prototype.allowMovement = true;
|
YANK.prototype.allowMovement = true;
|
||||||
|
|
||||||
YANK.prototype.dispose = function()
|
YANK.prototype.dispose = function()
|
||||||
{
|
{
|
||||||
|
this.__cursor.unsuppressEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
YANK.prototype.handler = function( e )
|
YANK.prototype.handler = function( e, sp )
|
||||||
{
|
{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
if( e.ModKeys || e.kMap( "i" ) ) return;
|
||||||
|
|
||||||
|
/** @type {Components.Vim.State.Registers} */
|
||||||
|
var reg = e.target.registers;
|
||||||
|
|
||||||
|
var cur = this.__cursor;
|
||||||
|
var feeder = cur.feeder;
|
||||||
|
|
||||||
|
var Triggered = false;
|
||||||
|
|
||||||
|
var newLine = false;
|
||||||
|
if( sp == undefined )
|
||||||
|
{
|
||||||
|
Triggered = true;
|
||||||
|
|
||||||
|
sp = this.__startX;
|
||||||
|
|
||||||
|
var currAp = cur.aPos;
|
||||||
|
if( this.__startX != currAp )
|
||||||
|
{
|
||||||
|
// Remove to start
|
||||||
|
if( e.kMap( "^" ) )
|
||||||
|
{
|
||||||
|
sp --;
|
||||||
|
}
|
||||||
|
// Remove char in cursor
|
||||||
|
else if( e.kMap( "l" ) )
|
||||||
|
{
|
||||||
|
cur.moveX( -1 );
|
||||||
|
}
|
||||||
|
// Remove char before cursor
|
||||||
|
else if( e.kMap( "h" ) )
|
||||||
|
{
|
||||||
|
sp = currAp;
|
||||||
|
}
|
||||||
|
// Remove the current and the following line
|
||||||
|
else if( e.kMap( "j" ) )
|
||||||
|
{
|
||||||
|
newLine = true;
|
||||||
|
cur.lineEnd( true );
|
||||||
|
sp = cur.aPos;
|
||||||
|
cur.moveY( -1 );
|
||||||
|
cur.lineStart();
|
||||||
|
this.__startX = cur.aPos;
|
||||||
|
}
|
||||||
|
// Remove the current and the preceding line
|
||||||
|
else if( e.kMap( "k" ) )
|
||||||
|
{
|
||||||
|
newLine = true;
|
||||||
|
cur.moveY( 1 );
|
||||||
|
cur.lineEnd( true );
|
||||||
|
sp = cur.aPos;
|
||||||
|
cur.moveY( -1 );
|
||||||
|
cur.lineStart();
|
||||||
|
}
|
||||||
|
else if( this.__startX < currAp )
|
||||||
|
{
|
||||||
|
// Swap the movement
|
||||||
|
// This is to move the REDO / UNDO Cursor
|
||||||
|
// position to the earlier position
|
||||||
|
sp = currAp;
|
||||||
|
cur.moveTo( this.__startX );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove the current line
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( e.kMap( "y" ) )
|
||||||
|
{
|
||||||
|
newLine = true;
|
||||||
|
cur.lineEnd( true );
|
||||||
|
sp = cur.aPos;
|
||||||
|
cur.lineStart();
|
||||||
|
}
|
||||||
|
else if( e.range )
|
||||||
|
{
|
||||||
|
sp = e.range.close;
|
||||||
|
cur.moveTo( e.range.open, true );
|
||||||
|
}
|
||||||
|
else if( e.kMap( "^" ) )
|
||||||
|
{
|
||||||
|
// Do nothing as nothing can be removed
|
||||||
|
// since there is no successful movement
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// this is the same as kMap( "h" ) above
|
||||||
|
else if( e.kMap( "$" ) )
|
||||||
|
{
|
||||||
|
sp = cur.aPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = sp;
|
||||||
|
var e = cur.aPos;
|
||||||
|
|
||||||
|
if( e < s )
|
||||||
|
{
|
||||||
|
s = cur.aPos;
|
||||||
|
e = sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur.moveTo( s );
|
||||||
|
|
||||||
|
var yText = cur.feeder.content.substring( s, e + 1 );
|
||||||
|
|
||||||
|
reg.yank( yText, newLine );
|
||||||
|
|
||||||
|
var nline = occurence( yText, "\n" );
|
||||||
|
if( nline )
|
||||||
|
{
|
||||||
|
this.__msg = Mesg( "LINES_YANKED", nline );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Triggered;
|
||||||
};
|
};
|
||||||
|
|
||||||
YANK.prototype.getMessage = function()
|
YANK.prototype.getMessage = function()
|
||||||
{
|
{
|
||||||
return "<TODO> YANK COMMAND";
|
return this.__msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
ns[ NS_EXPORT ]( EX_CLASS, "YANK", YANK );
|
ns[ NS_EXPORT ]( EX_CLASS, "YANK", YANK );
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
/** @type {System.Debug} */
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.Ex.Command} */
|
||||||
|
var ExCommand = __import( "Components.Vim.Ex.Command" );
|
||||||
|
|
||||||
var beep = ns[ NS_INVOKE ]( "Beep" );
|
var beep = ns[ NS_INVOKE ]( "Beep" );
|
||||||
|
|
||||||
var SHIFT = 1 << 9;
|
var SHIFT = 1 << 9;
|
||||||
@ -14,8 +18,12 @@
|
|||||||
var KEY_ALT = 18;
|
var KEY_ALT = 18;
|
||||||
|
|
||||||
var BACKSPACE = 8;
|
var BACKSPACE = 8;
|
||||||
|
var TAB = 9;
|
||||||
|
var ENTER = 13;
|
||||||
var DELETE = 46;
|
var DELETE = 46;
|
||||||
|
|
||||||
|
var UP = 38; var DOWN = 40; var LEFT = 37; var RIGHT = 39;
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
@ -35,6 +43,7 @@
|
|||||||
var F11 = 122; var F12 = 123;
|
var F11 = 122; var F12 = 123;
|
||||||
|
|
||||||
var COMMA = 188; var FULLSTOP = 190;
|
var COMMA = 188; var FULLSTOP = 190;
|
||||||
|
var SLASH = 191; var BACK_SLASH = 220;
|
||||||
|
|
||||||
var __maps = {};
|
var __maps = {};
|
||||||
var Map = function( str )
|
var Map = function( str )
|
||||||
@ -69,6 +78,13 @@
|
|||||||
{
|
{
|
||||||
case "BS": kCode = Mod + BACKSPACE; break;
|
case "BS": kCode = Mod + BACKSPACE; break;
|
||||||
case "Del": kCode = Mod + DELETE; break;
|
case "Del": kCode = Mod + DELETE; break;
|
||||||
|
case "Enter": kCode = Mod + ENTER; break;
|
||||||
|
case "Tab": kCode = Mod + TAB; break;
|
||||||
|
|
||||||
|
case "Up": kCode = Mod + UP; break;
|
||||||
|
case "Down": kCode = Mod + DOWN; break;
|
||||||
|
case "Left": kCode = Mod + LEFT; break;
|
||||||
|
case "Right": kCode = Mod + RIGHT; break;
|
||||||
|
|
||||||
case "A": Mod = SHIFT; case "a": kCode = Mod + A; break;
|
case "A": Mod = SHIFT; case "a": kCode = Mod + A; break;
|
||||||
case "B": Mod = SHIFT; case "b": kCode = Mod + B; break;
|
case "B": Mod = SHIFT; case "b": kCode = Mod + B; break;
|
||||||
@ -126,14 +142,18 @@
|
|||||||
this.__sfeeder = vimArea.statusFeeder;
|
this.__sfeeder = vimArea.statusFeeder;
|
||||||
|
|
||||||
this.__ccur = this.__cfeeder.cursor;
|
this.__ccur = this.__cfeeder.cursor;
|
||||||
|
|
||||||
|
// Dived composite command handler
|
||||||
|
// Has full control of the key input, except Esc
|
||||||
|
this.__divedCCmd = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
Controls.prototype.__comp = function( e, handler )
|
Controls.prototype.__composite = function( e, handler )
|
||||||
{
|
{
|
||||||
if( handler )
|
if( handler )
|
||||||
{
|
{
|
||||||
if( !this.__compReg ) this.__compReg = [];
|
if( !this.__compositeReg ) this.__compositeReg = [];
|
||||||
this.__compReg.push({
|
this.__compositeReg.push({
|
||||||
keys: Array.prototype.slice.call( arguments, 2 )
|
keys: Array.prototype.slice.call( arguments, 2 )
|
||||||
, handler: handler
|
, handler: handler
|
||||||
, i: 0
|
, i: 0
|
||||||
@ -143,9 +163,9 @@
|
|||||||
|
|
||||||
var kCode = e.keyCode;
|
var kCode = e.keyCode;
|
||||||
|
|
||||||
for( var i = 0; i < this.__compReg.length; i ++ )
|
for( var i = 0; i < this.__compositeReg.length; i ++ )
|
||||||
{
|
{
|
||||||
var compReg = this.__compReg[i];
|
var compReg = this.__compositeReg[i];
|
||||||
var keys = compReg.keys;
|
var keys = compReg.keys;
|
||||||
|
|
||||||
if( keys[ compReg.i ++ ] == kCode )
|
if( keys[ compReg.i ++ ] == kCode )
|
||||||
@ -153,7 +173,7 @@
|
|||||||
if( compReg.i == keys.length )
|
if( compReg.i == keys.length )
|
||||||
{
|
{
|
||||||
compReg.handler( e );
|
compReg.handler( e );
|
||||||
this.__compReg = null;
|
this.__compositeReg = null;
|
||||||
this.__cMovement = false;
|
this.__cMovement = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +181,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( this.__compReg ) beep();
|
if( this.__compositeReg ) beep();
|
||||||
this.__compReg = null;
|
this.__compositeReg = null;
|
||||||
this.__cMovement = false;
|
this.__cMovement = false;
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@ -178,22 +198,54 @@
|
|||||||
case SHIFT + A: // Append at the line end
|
case SHIFT + A: // Append at the line end
|
||||||
ccur.lineEnd();
|
ccur.lineEnd();
|
||||||
case A: // Append
|
case A: // Append
|
||||||
this.__cMoveX( 1, true, true );
|
ccur.moveX( 1, true, true );
|
||||||
case I: // Insert
|
case I: // Insert
|
||||||
ccur.openAction( "INSERT" );
|
ccur.openAction( "INSERT" );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SHIFT + O: // new line before insert
|
||||||
|
ccur.lineStart();
|
||||||
|
ccur.openAction( "INSERT" );
|
||||||
|
ccur.action.handler( new InputEvent( e.sender, "Enter" ) );
|
||||||
|
ccur.moveY( -1 );
|
||||||
|
break;
|
||||||
|
case O: // new line insert
|
||||||
|
ccur.lineEnd( true );
|
||||||
|
ccur.openAction( "INSERT" );
|
||||||
|
ccur.action.handler( new InputEvent( e.sender, "Enter" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
case U: // Undo
|
case U: // Undo
|
||||||
ccur.openRunAction( "UNDO", e );
|
ccur.openRunAction( "UNDO", e );
|
||||||
break;
|
break;
|
||||||
case CTRL + R: // Redo
|
case CTRL + R: // Redo
|
||||||
ccur.openRunAction( "REDO", e );
|
ccur.openRunAction( "REDO", e );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D: // Del with motion
|
case D: // Del with motion
|
||||||
ccur.openAction( "DELETE" );
|
ccur.openAction( "DELETE" );
|
||||||
break;
|
break;
|
||||||
case X: // Del
|
case Y: // Yank with motion
|
||||||
|
ccur.openAction( "YANK" );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case P: // Put
|
||||||
|
ccur.suppressEvent();
|
||||||
|
ccur.moveX( 1, false, true );
|
||||||
|
ccur.unsuppressEvent();
|
||||||
|
case SHIFT + P: // Put before
|
||||||
|
ccur.openRunAction( "PUT", e );
|
||||||
|
break;
|
||||||
|
|
||||||
case SHIFT + X: // Delete before
|
case SHIFT + X: // Delete before
|
||||||
|
if( !this.__cMoveX( -1 ) ) break;
|
||||||
|
case X: // Del
|
||||||
|
if( ccur.getLine().content == "" )
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ccur.openRunAction( "DELETE", e, ccur.aPos );
|
||||||
break;
|
break;
|
||||||
case SHIFT + U: // Undo previous changes in oneline
|
case SHIFT + U: // Undo previous changes in oneline
|
||||||
break;
|
break;
|
||||||
@ -226,7 +278,12 @@
|
|||||||
|
|
||||||
var x = ccur.X;
|
var x = ccur.X;
|
||||||
ccur.moveX( a, b, c || ccur.pSpace );
|
ccur.moveX( a, b, c || ccur.pSpace );
|
||||||
if( ccur.X == x ) beep();
|
if( ccur.X == x )
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
Controls.prototype.__cMoveY = function( a )
|
Controls.prototype.__cMoveY = function( a )
|
||||||
@ -238,20 +295,22 @@
|
|||||||
ccur.moveY( a );
|
ccur.moveY( a );
|
||||||
if( y == ( ccur.Y + cfeeder.panY ) )
|
if( y == ( ccur.Y + cfeeder.panY ) )
|
||||||
{
|
{
|
||||||
if( 0 < a && !cfeeder.EOF ) return;
|
if( 0 < a && !cfeeder.EOF ) return true;
|
||||||
beep();
|
beep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Controls.prototype.__cursorCommand = function( e )
|
Controls.prototype.__cursorCommand = function( e )
|
||||||
{
|
{
|
||||||
var kCode = e.keyCode;
|
var kCode = e.keyCode;
|
||||||
|
|
||||||
if( this.__cMovement && this.__comp )
|
if( this.__cMovement )
|
||||||
{
|
{
|
||||||
if( !e.ModKeys )
|
if( !e.ModKeys )
|
||||||
{
|
{
|
||||||
this.__comp( e );
|
this.__composite( e );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,14 +329,16 @@
|
|||||||
case J: this.__cMoveY( 1 ); break; // Down
|
case J: this.__cMoveY( 1 ); break; // Down
|
||||||
|
|
||||||
case CTRL + F: // Page Down
|
case CTRL + F: // Page Down
|
||||||
if( cfeeder.firstBuffer.next.placeholder )
|
if( cfeeder.firstBuffer.nextLine.placeholder )
|
||||||
{
|
{
|
||||||
beep();
|
beep();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var oPan = cfeeder.panY;
|
var oPan = cfeeder.panY;
|
||||||
cfeeder.pan( undefined, vima.rows - 1 );
|
cfeeder.pan( undefined, cfeeder.moreAt );
|
||||||
|
cfeeder.softReset();
|
||||||
|
|
||||||
ccur.moveY( -ccur.Y );
|
ccur.moveY( -ccur.Y );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -287,7 +348,9 @@
|
|||||||
beep();
|
beep();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cfeeder.pan( undefined, -vima.rows + 1 );
|
cfeeder.pan( undefined, -cfeeder.moreAt );
|
||||||
|
cfeeder.softReset();
|
||||||
|
|
||||||
ccur.moveY( -ccur.Y );
|
ccur.moveY( -ccur.Y );
|
||||||
if( !cfeeder.EOF ) ccur.moveY( cfeeder.moreAt );
|
if( !cfeeder.EOF ) ccur.moveY( cfeeder.moreAt );
|
||||||
break;
|
break;
|
||||||
@ -340,7 +403,7 @@
|
|||||||
this.__cMovement = true;
|
this.__cMovement = true;
|
||||||
|
|
||||||
// Word boundary
|
// Word boundary
|
||||||
this.__comp( e, function( e2 ) {
|
this.__composite( e, function( e2 ) {
|
||||||
var WordMatch = analyzer.wordAt( ccur.aPos );
|
var WordMatch = analyzer.wordAt( ccur.aPos );
|
||||||
e2.__range = WordMatch;
|
e2.__range = WordMatch;
|
||||||
}, W );
|
}, W );
|
||||||
@ -359,25 +422,36 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Bracket boundaries
|
// Bracket boundaries
|
||||||
this.__comp( e, bracket , SHIFT + _0 );
|
this.__composite( e, bracket , SHIFT + _0 );
|
||||||
this.__comp( e, bracket, SHIFT + _9 );
|
this.__composite( e, bracket, SHIFT + _9 );
|
||||||
this.__comp( e, squareBracket, S_BRACKET_L );
|
this.__composite( e, squareBracket, S_BRACKET_L );
|
||||||
this.__comp( e, squareBracket, S_BRACKET_R );
|
this.__composite( e, squareBracket, S_BRACKET_R );
|
||||||
this.__comp( e, curlyBracket, SHIFT + S_BRACKET_L );
|
this.__composite( e, curlyBracket, SHIFT + S_BRACKET_L );
|
||||||
this.__comp( e, curlyBracket, SHIFT + S_BRACKET_R );
|
this.__composite( e, curlyBracket, SHIFT + S_BRACKET_R );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case G: // Go to top
|
case G: // Go to top
|
||||||
this.__cMovement = true;
|
this.__cMovement = true;
|
||||||
this.__comp( e, function(){
|
this.__composite( e, function(){
|
||||||
ccur.moveY( -Number.MAX_VALUE );
|
ccur.moveY( -Number.MAX_VALUE );
|
||||||
ccur.moveX( -Number.MAX_VALUE, true );
|
ccur.moveX( -Number.MAX_VALUE, true );
|
||||||
}, G );
|
}, G );
|
||||||
this.__comp( e, function(){
|
this.__composite( e, function(){
|
||||||
ccur.openRunAction( "PRINT_HEX", e );
|
ccur.openRunAction( "PRINT_HEX", e );
|
||||||
}, _8 );
|
}, _8 );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SHIFT + N: // Next Search
|
||||||
|
case N: // Next Search
|
||||||
|
ccur.openRunAction( "FIND", e );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SLASH: // "/" Search movement
|
||||||
|
this.__cMovement = true;
|
||||||
|
|
||||||
|
this.__divedCCmd = new ExCommand( ccur, "/" );
|
||||||
|
this.__divedCCmd.handler( e );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cursorHandled = false;
|
cursorHandled = false;
|
||||||
}
|
}
|
||||||
@ -398,12 +472,40 @@
|
|||||||
) return;
|
) return;
|
||||||
|
|
||||||
// Clear composite command
|
// Clear composite command
|
||||||
if( e.Escape && this.__compReg )
|
if( e.Escape )
|
||||||
{
|
{
|
||||||
this.__compReg = null;
|
var b = false;
|
||||||
this.__cMovement = false;
|
this.__cMovement = false;
|
||||||
beep();
|
|
||||||
return;
|
if( this.__compositeReg )
|
||||||
|
{
|
||||||
|
b = true;
|
||||||
|
this.__compositeReg = null;
|
||||||
|
}
|
||||||
|
else if( this.__divedCCmd )
|
||||||
|
{
|
||||||
|
b = true;
|
||||||
|
this.__divedCCmd.dispose();
|
||||||
|
this.__divedCCmd = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( b )
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this.__divedCCmd )
|
||||||
|
{
|
||||||
|
if( this.__divedCCmd.handler( e ) )
|
||||||
|
{
|
||||||
|
this.__divedCCmd.dispose();
|
||||||
|
this.__cMovement = false;
|
||||||
|
this.__divedCCmd = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( e.canceled ) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cfeeder = this.__cfeeder;
|
var cfeeder = this.__cfeeder;
|
||||||
@ -422,7 +524,15 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( ccur.action.allowMovement )
|
if( ccur.action.allowMovement )
|
||||||
|
{
|
||||||
|
var SubCommand = !this.__compositeReg;
|
||||||
this.__cursorCommand( e, kCode );
|
this.__cursorCommand( e, kCode );
|
||||||
|
if( SubCommand && this.__compositeReg )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ccur.action.handler( e ) )
|
if( ccur.action.handler( e ) )
|
||||||
{
|
{
|
||||||
@ -440,28 +550,43 @@
|
|||||||
|
|
||||||
var InputEvent = function( sender, e )
|
var InputEvent = function( sender, e )
|
||||||
{
|
{
|
||||||
this.__e = e;
|
|
||||||
this.__target = sender;
|
this.__target = sender;
|
||||||
|
this.__canceled = false;
|
||||||
|
|
||||||
var c = this.__e.keyCode;
|
if( typeof( e ) == "string" )
|
||||||
|
{
|
||||||
|
this.__key = e;
|
||||||
|
this.__modKeys = 0;
|
||||||
|
this.__kCode = Map( e );
|
||||||
|
this.__escape = this.__kCode == ESC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.__e = e;
|
||||||
|
|
||||||
this.__escape = c == ESC || ( e.ctrlKey && c == C );
|
var c = this.__e.keyCode;
|
||||||
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.__escape = c == ESC || ( e.ctrlKey && c == C );
|
||||||
this.__key = e.key;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
this.__range = null;
|
this.__range = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
InputEvent.prototype.cancel = function() { this.__canceled = true; };
|
||||||
|
|
||||||
__readOnly( InputEvent.prototype, "target", function() { return this.__target; } );
|
__readOnly( InputEvent.prototype, "target", function() { return this.__target; } );
|
||||||
__readOnly( InputEvent.prototype, "key", function() { return this.__key; } );
|
__readOnly( InputEvent.prototype, "key", function() { return this.__key; } );
|
||||||
__readOnly( InputEvent.prototype, "keyCode", function() { return this.__kCode; } );
|
__readOnly( InputEvent.prototype, "keyCode", function() { return this.__kCode; } );
|
||||||
__readOnly( InputEvent.prototype, "ModKeys", function() { return this.__modKeys; } );
|
__readOnly( InputEvent.prototype, "ModKeys", function() { return this.__modKeys; } );
|
||||||
__readOnly( InputEvent.prototype, "Escape", function() { return this.__escape; } );
|
__readOnly( InputEvent.prototype, "Escape", function() { return this.__escape; } );
|
||||||
|
__readOnly( InputEvent.prototype, "canceled", function() { return this.__canceled; } );
|
||||||
|
|
||||||
__readOnly( InputEvent.prototype, "range", function() {
|
__readOnly( InputEvent.prototype, "range", function() {
|
||||||
|
|
||||||
|
@ -83,6 +83,9 @@
|
|||||||
this.pSpace = false;
|
this.pSpace = false;
|
||||||
|
|
||||||
this.__suppEvt = 0;
|
this.__suppEvt = 0;
|
||||||
|
|
||||||
|
// Offset compensation for max filled wrapped line
|
||||||
|
this.__off = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set by VimArea
|
// Set by VimArea
|
||||||
@ -92,7 +95,14 @@
|
|||||||
Cursor.prototype.moveTo = function( aPos, phantomSpace )
|
Cursor.prototype.moveTo = function( aPos, phantomSpace )
|
||||||
{
|
{
|
||||||
var content = this.feeder.content;
|
var content = this.feeder.content;
|
||||||
var lastLineNum = this.getLine().lineNum;
|
var pline = this.getLine();
|
||||||
|
var lastLineNum = pline.lineNum;
|
||||||
|
|
||||||
|
if( pline.placeholder )
|
||||||
|
{
|
||||||
|
lastLineNum = 0;
|
||||||
|
this.Y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
var expLineNum = 0;
|
var expLineNum = 0;
|
||||||
var lineStart = 0;
|
var lineStart = 0;
|
||||||
@ -111,7 +121,11 @@
|
|||||||
var jumpY = expLineNum - lastLineNum;
|
var jumpY = expLineNum - lastLineNum;
|
||||||
var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart;
|
var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart;
|
||||||
|
|
||||||
|
jumpX += Math.ceil( jumpX / pline.cols ) - 1;
|
||||||
|
|
||||||
if( jumpY ) this.moveY( jumpY );
|
if( jumpY ) this.moveY( jumpY );
|
||||||
|
|
||||||
|
// This needed because first line does not contain first "\n" character
|
||||||
if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --;
|
if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --;
|
||||||
|
|
||||||
this.moveX( - Number.MAX_VALUE );
|
this.moveX( - Number.MAX_VALUE );
|
||||||
@ -123,13 +137,20 @@
|
|||||||
Cursor.prototype.moveX = function( d, penetrate, phantomSpace )
|
Cursor.prototype.moveX = function( d, penetrate, phantomSpace )
|
||||||
{
|
{
|
||||||
var x = this.pX;
|
var x = this.pX;
|
||||||
|
|
||||||
var updatePx = Boolean( d );
|
var updatePx = Boolean( d );
|
||||||
|
|
||||||
|
if( 0 < this.__off )
|
||||||
|
{
|
||||||
|
d += this.__off;
|
||||||
|
this.__off = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if( updatePx ) x = this.X + d;
|
if( updatePx ) x = this.X + d;
|
||||||
|
|
||||||
if( !d ) d = 1;
|
if( !d ) d = 1;
|
||||||
|
|
||||||
var buffs = this.feeder.lineBuffers;
|
var feeder = this.feeder;
|
||||||
|
var buffs = feeder.lineBuffers;
|
||||||
|
|
||||||
if( penetrate )
|
if( penetrate )
|
||||||
{
|
{
|
||||||
@ -146,23 +167,61 @@
|
|||||||
var content = line.visualLines.join( "\n" );
|
var content = line.visualLines.join( "\n" );
|
||||||
var cLen = content.length;
|
var cLen = content.length;
|
||||||
|
|
||||||
|
var lineEnd = 0;
|
||||||
|
var hasPhantomSpace = true;
|
||||||
|
|
||||||
|
// Empty lines has length of 1
|
||||||
|
// If length larger than a, need to compensate the lineEnd
|
||||||
|
// for phantomSpace
|
||||||
|
if( 1 < cLen )
|
||||||
|
{
|
||||||
|
// Begin check if whether this line contains phantomSpace
|
||||||
|
var lineNum = line.lineNum - 1;
|
||||||
|
var str = feeder.content;
|
||||||
|
for( var i = str.indexOf( "\n" ), j = 0; 0 <= i; i = str.indexOf( "\n", i ), j ++ )
|
||||||
|
{
|
||||||
|
if( lineNum == j ) break;
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( j == 0 && i == -1 ) i = 0;
|
||||||
|
|
||||||
|
var end = str.indexOf( "\n", i + 1 );
|
||||||
|
end = end == -1 ? str.length : end;
|
||||||
|
|
||||||
|
// Actual LineLength
|
||||||
|
var hasPhantomSpace = 0 < ( end - i - 1 ) % line.cols;
|
||||||
|
|
||||||
|
if( hasPhantomSpace )
|
||||||
|
{
|
||||||
|
lineEnd = phantomSpace ? cLen - 1 : cLen - 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lineEnd = phantomSpace ? cLen : cLen - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var c = content[ x ];
|
var c = content[ x ];
|
||||||
|
|
||||||
// Motion includes empty lines before cursor end
|
// Whether x is at line boundary
|
||||||
if( ( phantomSpace && cLen - 1 <= x ) || ( cLen == 1 && c == undefined ) )
|
var boundary = c == undefined || ( cLen == x + 1 && c == " " );
|
||||||
|
|
||||||
|
if( boundary )
|
||||||
{
|
{
|
||||||
x = 0 < d ? cLen - 1 : 0;
|
x = 0 < d ? lineEnd : 0;
|
||||||
}
|
|
||||||
// ( 2 < cLen ) motion excludes empty lines at cursor end
|
|
||||||
else if( ( 2 <= cLen && x == cLen - 1 && c == " " ) || c == undefined )
|
|
||||||
{
|
|
||||||
x = 0 < d ? cLen - 2 : 0;
|
|
||||||
}
|
}
|
||||||
else if( c == "\n" )
|
else if( c == "\n" )
|
||||||
{
|
{
|
||||||
x += d;
|
x += d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wordwrap phantomSpace movement compensation on max filled lines
|
||||||
|
if( feeder.wrap && boundary && !hasPhantomSpace && phantomSpace )
|
||||||
|
{
|
||||||
|
this.__off = 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.X = x;
|
this.X = x;
|
||||||
|
|
||||||
if( updatePx )
|
if( updatePx )
|
||||||
@ -170,6 +229,7 @@
|
|||||||
this.pX = x;
|
this.pX = x;
|
||||||
this.updatePosition();
|
this.updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Cursor.prototype.lineStart = function()
|
Cursor.prototype.lineStart = function()
|
||||||
@ -186,10 +246,11 @@
|
|||||||
|
|
||||||
Cursor.prototype.updatePosition = function()
|
Cursor.prototype.updatePosition = function()
|
||||||
{
|
{
|
||||||
var P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
|
var feeder = this.feeder;
|
||||||
|
var P = this.X + LineOffset( feeder.lineBuffers, this.Y ) + this.__off;
|
||||||
|
|
||||||
this.PStart = P;
|
this.PStart = P;
|
||||||
this.PEnd = P + 1;
|
this.PEnd = P + 1;
|
||||||
this.__p = P;
|
|
||||||
|
|
||||||
this.__visualUpdate();
|
this.__visualUpdate();
|
||||||
};
|
};
|
||||||
@ -310,6 +371,9 @@
|
|||||||
Cursor.prototype.openAction = function( name )
|
Cursor.prototype.openAction = function( name )
|
||||||
{
|
{
|
||||||
if( this.action ) this.action.dispose();
|
if( this.action ) this.action.dispose();
|
||||||
|
|
||||||
|
debug.Info( "openAction: " + name );
|
||||||
|
|
||||||
this.action = new (Actions[ name ])( this );
|
this.action = new (Actions[ name ])( this );
|
||||||
this.__pulseMsg = null;
|
this.__pulseMsg = null;
|
||||||
|
|
||||||
@ -323,6 +387,8 @@
|
|||||||
this.__pulseMsg = this.action.getMessage();
|
this.__pulseMsg = this.action.getMessage();
|
||||||
this.action = null;
|
this.action = null;
|
||||||
|
|
||||||
|
debug.Info( "closeAction: " + this.__pulseMsg );
|
||||||
|
|
||||||
// Reset the analyzed content
|
// Reset the analyzed content
|
||||||
this.Vim.contentAnalyzer.reset();
|
this.Vim.contentAnalyzer.reset();
|
||||||
|
|
||||||
@ -330,11 +396,11 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Open, Run, then close an action
|
// Open, Run, then close an action
|
||||||
Cursor.prototype.openRunAction = function( name, e )
|
Cursor.prototype.openRunAction = function( name, e, arg1 )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.IAction} */
|
/** @type {Components.Vim.IAction} */
|
||||||
var action = new (Actions[ name ])( this );
|
var action = new (Actions[ name ])( this );
|
||||||
action.handler( e );
|
action.handler( e, arg1 );
|
||||||
this.__pulseMsg = action.getMessage();
|
this.__pulseMsg = action.getMessage();
|
||||||
action.dispose();
|
action.dispose();
|
||||||
|
|
||||||
@ -431,6 +497,8 @@
|
|||||||
return p;
|
return p;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
__readOnly( Cursor.prototype, "face", function() { return "\u2588"; } );
|
||||||
|
|
||||||
__readOnly( Cursor.prototype, "message", function()
|
__readOnly( Cursor.prototype, "message", function()
|
||||||
{
|
{
|
||||||
if( this.__pulseMsg )
|
if( this.__pulseMsg )
|
||||||
|
228
botanjs/src/Components/Vim/Ex/Command.js
Normal file
228
botanjs/src/Components/Vim/Ex/Command.js
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.Ex" );
|
||||||
|
|
||||||
|
/** @type {System.Cycle} */
|
||||||
|
var Cycle = __import( "System.Cycle" );
|
||||||
|
/** @type {System.Debug} */
|
||||||
|
var debug = __import( "System.Debug" );
|
||||||
|
/** @type {System.utils.Perf} */
|
||||||
|
var Perf = __import( "System.utils.Perf" );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.State.History} */
|
||||||
|
var History = __import( "Components.Vim.State.History" );
|
||||||
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
var beep = __import( "Components.Vim.Beep" );
|
||||||
|
|
||||||
|
// This is for security & privacy concerns?
|
||||||
|
var ZMap = {
|
||||||
|
"/": Perf.uuid
|
||||||
|
, ":" : Perf.uuid
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @type {Components.Vim.Cursor.IAction} */
|
||||||
|
var Command = function( Cursor, Mode )
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
if( !ZMap[ Mode ] ) throw new Error( "Unsupport mode: " + Mode );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.Cursor} */
|
||||||
|
this.__cursor = Cursor;
|
||||||
|
|
||||||
|
this.__statusBar = Cursor.Vim.statusBar;
|
||||||
|
|
||||||
|
this.__mode = Mode;
|
||||||
|
this.__hist = new History( ZMap[ Mode ] );
|
||||||
|
|
||||||
|
this.__command = [];
|
||||||
|
this.__currentCommand = null;
|
||||||
|
this.__blinkId = "ExCommandBlinkCycle" + Perf.uuid;
|
||||||
|
this.__curPos = 0;
|
||||||
|
|
||||||
|
var feeder = Cursor.feeder;
|
||||||
|
|
||||||
|
var __blink = false;
|
||||||
|
var __holdBlink = false;
|
||||||
|
this.__blink = function()
|
||||||
|
{
|
||||||
|
__blink = true;
|
||||||
|
__holdBlink = true
|
||||||
|
};
|
||||||
|
|
||||||
|
Cycle.perma( this.__blinkId, function()
|
||||||
|
{
|
||||||
|
if( __holdBlink ) __holdBlink = false;
|
||||||
|
else __blink = !__blink;
|
||||||
|
|
||||||
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
|
}, 600 );
|
||||||
|
|
||||||
|
this.__doBlink = function()
|
||||||
|
{
|
||||||
|
var c = "";
|
||||||
|
var comm = _self.__command;
|
||||||
|
var pos = _self.__curPos;
|
||||||
|
var cLen = comm.length;
|
||||||
|
var faced = true;
|
||||||
|
|
||||||
|
for( var i = 0; i < cLen; i ++ )
|
||||||
|
{
|
||||||
|
var v = comm[i];
|
||||||
|
if( __blink && i == pos )
|
||||||
|
{
|
||||||
|
face = true;
|
||||||
|
v = Cursor.face + v.substr( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
c+= v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( __blink && cLen <= pos )
|
||||||
|
{
|
||||||
|
c += Cursor.face;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.__statusBar.override = this.__doBlink;
|
||||||
|
};
|
||||||
|
|
||||||
|
Command.prototype.dispose = function()
|
||||||
|
{
|
||||||
|
this.__statusBar.override = null;
|
||||||
|
|
||||||
|
Cycle.permaRemove( this.__blinkId );
|
||||||
|
var feeder = this.__cursor.feeder;
|
||||||
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
|
};
|
||||||
|
|
||||||
|
Command.prototype.handler = function( e )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if( e.ModKeys ) return;
|
||||||
|
|
||||||
|
this.__blink();
|
||||||
|
|
||||||
|
var InputKey = null;
|
||||||
|
|
||||||
|
var histNav = false;
|
||||||
|
|
||||||
|
if( e.kMap( "Tab" ) )
|
||||||
|
{
|
||||||
|
InputKey = "^I";
|
||||||
|
}
|
||||||
|
else if( e.kMap( "C-v" ) )
|
||||||
|
{
|
||||||
|
this.__direct = true;
|
||||||
|
}
|
||||||
|
else if( e.kMap( "BS" ) )
|
||||||
|
{
|
||||||
|
if( this.__curPos == 1 && 1 < this.__command.length )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
this.__command.splice( --this.__curPos, 1 );
|
||||||
|
if( this.__command.length == 0 )
|
||||||
|
{
|
||||||
|
e.cancel();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( e.kMap( "Del" ) )
|
||||||
|
{
|
||||||
|
this.__command.splice( this.__curPos, 1 );
|
||||||
|
}
|
||||||
|
else if( e.kMap( "Enter" ) )
|
||||||
|
{
|
||||||
|
this.__process( e );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if( e.kMap( "Left" ) )
|
||||||
|
{
|
||||||
|
if( 1 < this.__curPos ) this.__curPos --;
|
||||||
|
}
|
||||||
|
else if( e.kMap( "Right" ) )
|
||||||
|
{
|
||||||
|
if( this.__curPos < this.__command.length )
|
||||||
|
this.__curPos ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// History stepping
|
||||||
|
else if( histNav = e.kMap( "Up" ) ) // History navigations
|
||||||
|
{
|
||||||
|
if( !this.__currentCommand )
|
||||||
|
{
|
||||||
|
this.__currentCommand = this.__command;
|
||||||
|
}
|
||||||
|
|
||||||
|
var n = this.__hist.prev( this.__currentCommand );
|
||||||
|
|
||||||
|
if( n )
|
||||||
|
{
|
||||||
|
this.__command = n;
|
||||||
|
this.__curPos = n.length;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
beep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( histNav = e.kMap( "Down" ) )
|
||||||
|
{
|
||||||
|
var n = this.__hist.next( this.__currentCommand );
|
||||||
|
|
||||||
|
if( n )
|
||||||
|
{
|
||||||
|
this.__command = n;
|
||||||
|
this.__curPos = n.length;
|
||||||
|
}
|
||||||
|
else if( this.__currentCommand )
|
||||||
|
{
|
||||||
|
this.__command = this.__currentCommand;
|
||||||
|
this.__currentCommand = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
else beep();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InputKey = e.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( InputKey != null )
|
||||||
|
{
|
||||||
|
this.__command.splice( this.__curPos ++, 0, InputKey );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !histNav )
|
||||||
|
{
|
||||||
|
this.__hist.reset();
|
||||||
|
if( this.__currentCommand ) this.__currentCommand = this.__command;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.cancel();
|
||||||
|
|
||||||
|
var feeder = this.__cursor.feeder;
|
||||||
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
|
};
|
||||||
|
|
||||||
|
Command.prototype.__process = function( e )
|
||||||
|
{
|
||||||
|
this.__hist.push( this.__command );
|
||||||
|
|
||||||
|
var action = "";
|
||||||
|
switch( this.__mode )
|
||||||
|
{
|
||||||
|
case "/":
|
||||||
|
action = "FIND";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cur = this.__cursor;
|
||||||
|
cur.suppressEvent();
|
||||||
|
this.__cursor.openRunAction( action, e, this.__command.slice() );
|
||||||
|
cur.unsuppressEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "Command", Command );
|
||||||
|
})();
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
||||||
|
|
||||||
var LineBuffer = function( cols, nextLineBuffer )
|
var LineBuffer = function( cols, nextLineBuffer )
|
||||||
{
|
{
|
||||||
this.prev = null;
|
this.prev = null;
|
||||||
@ -60,6 +62,12 @@
|
|||||||
|
|
||||||
line += c;
|
line += c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !br && i == this.cols && content[i] == "\n" )
|
||||||
|
{
|
||||||
|
i ++;
|
||||||
|
br = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -97,7 +105,8 @@
|
|||||||
|
|
||||||
LineBuffer.prototype.toString = function()
|
LineBuffer.prototype.toString = function()
|
||||||
{
|
{
|
||||||
if( this.content.length < this.cols )
|
var c = this.cols - occurence( this.content, "\t" ) * ( this.tabWidth - 1 );
|
||||||
|
if( this.content.length < c )
|
||||||
{
|
{
|
||||||
return this.content + " ";
|
return this.content + " ";
|
||||||
}
|
}
|
||||||
|
@ -141,17 +141,17 @@
|
|||||||
// Y cannot be negative
|
// Y cannot be negative
|
||||||
if( Y < 0 ) Y = 0;
|
if( Y < 0 ) Y = 0;
|
||||||
|
|
||||||
|
// Compensate the last "\n" content placeholder
|
||||||
|
var cont = this.content.slice( 0, -1 );
|
||||||
if( 0 < Y )
|
if( 0 < Y )
|
||||||
{
|
{
|
||||||
f = this.content.indexOf( "\n" );
|
f = cont.indexOf( "\n" );
|
||||||
for( i = 1; f != -1 && i < Y; i ++ )
|
for( i = 1; f != -1 && i < Y; i ++ )
|
||||||
{
|
{
|
||||||
var a = this.content.indexOf( "\n", f + 1 );
|
var a = cont.indexOf( "\n", f + 1 );
|
||||||
if( a == -1 )
|
if( a == -1 )
|
||||||
{
|
{
|
||||||
Y = i - 1;
|
Y = i;
|
||||||
// -2 to compensate the last "\n" content placeholder
|
|
||||||
f -= 2;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
f = a;
|
f = a;
|
||||||
@ -226,9 +226,16 @@
|
|||||||
__readOnly( Feeder.prototype, "docPos", function() {
|
__readOnly( Feeder.prototype, "docPos", function() {
|
||||||
var pos = "ALL";
|
var pos = "ALL";
|
||||||
|
|
||||||
if( 0 < this.panY && this.EOF )
|
if( 0 < this.panY )
|
||||||
{
|
{
|
||||||
pos = "BOTTOM";
|
if( this.EOF )
|
||||||
|
{
|
||||||
|
pos = "BOTTOM";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pos = Math.floor( ( this.panY / ( this.linesTotal - ( this.__rows - 1 ) ) ) * 100 ) + "%";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
96
botanjs/src/Components/Vim/State/History.js
Normal file
96
botanjs/src/Components/Vim/State/History.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.State" );
|
||||||
|
|
||||||
|
/** @type {System.Debug} */
|
||||||
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
// private static
|
||||||
|
var Zones = {};
|
||||||
|
|
||||||
|
var PartialBA = function( a, b )
|
||||||
|
{
|
||||||
|
var l = b.length;
|
||||||
|
if( a.length < l ) return false;
|
||||||
|
|
||||||
|
for( var i = 0; i < l; i ++ )
|
||||||
|
{
|
||||||
|
if( a[ i ] != b[ i ] ) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var ExactAB = function( a, b )
|
||||||
|
{
|
||||||
|
var l = a.length < b.length ? b.length : a.length;
|
||||||
|
for( var i = 0; i < l; i ++ )
|
||||||
|
{
|
||||||
|
if( a[ i ] != b[ i ] ) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var History = function( z )
|
||||||
|
{
|
||||||
|
if( !Zones[ z ] ) Zones[ z ] = [];
|
||||||
|
|
||||||
|
this.__pi = 0;
|
||||||
|
this.__zone = Zones[ z ];
|
||||||
|
this.reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
History.prototype.push = function( stack )
|
||||||
|
{
|
||||||
|
if( this.__zone.length
|
||||||
|
&& ExactAB( this.__zone[ this.__zone.length - 1 ], stack )
|
||||||
|
) {
|
||||||
|
debug.Info( "This is the previous command, skipping" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.__zone.push( stack );
|
||||||
|
};
|
||||||
|
|
||||||
|
History.prototype.prev = function( stack )
|
||||||
|
{
|
||||||
|
if( this.__zone.length <= this.__i ) this.reset();
|
||||||
|
|
||||||
|
while( -1 < this.__i )
|
||||||
|
{
|
||||||
|
var st = this.__zone[ this.__i -- ];
|
||||||
|
if( st && PartialBA( st, stack ) )
|
||||||
|
{
|
||||||
|
return st.slice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
History.prototype.next = function( stack )
|
||||||
|
{
|
||||||
|
if( this.__i < 0 )
|
||||||
|
{
|
||||||
|
this.__i ++;
|
||||||
|
this.next( stack );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( this.__i < this.__zone.length )
|
||||||
|
{
|
||||||
|
var st = this.__zone[ this.__i ++ ];
|
||||||
|
if( st && PartialBA( st, stack ) )
|
||||||
|
{
|
||||||
|
return st.slice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
History.prototype.reset = function()
|
||||||
|
{
|
||||||
|
this.__i = this.__zone.length - 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "History", History );
|
||||||
|
})();
|
@ -15,25 +15,41 @@
|
|||||||
*/
|
*/
|
||||||
var ns = __namespace( "Components.Vim.State" );
|
var ns = __namespace( "Components.Vim.State" );
|
||||||
|
|
||||||
|
var Register = function( str, n )
|
||||||
|
{
|
||||||
|
this.__str = str + "";
|
||||||
|
this.newLine = Boolean( n );
|
||||||
|
};
|
||||||
|
|
||||||
|
Register.prototype.newLine = false;
|
||||||
|
|
||||||
|
Register.prototype.toString = function() { return this.__str; };
|
||||||
|
Register.prototype.indexOf = function( a, b ) { return this.__str.indexOf( a, b ); };
|
||||||
|
|
||||||
|
__readOnly( Register.prototype, "length", function() { return this.__str.length; } );
|
||||||
|
|
||||||
|
|
||||||
var Registers = function()
|
var Registers = function()
|
||||||
{
|
{
|
||||||
this.__registers = {};
|
this.__registers = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
Registers.prototype.unnamed = function( str )
|
Registers.prototype.__unnamed = function( reg )
|
||||||
{
|
{
|
||||||
this.__registers[ "\"" ] = str;
|
this.__registers[ "\"" ] = reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
Registers.prototype.yank = function( str )
|
Registers.prototype.yank = function( str, newLine )
|
||||||
{
|
{
|
||||||
this.unnamed( str );
|
var reg = new Register( str, newLine );
|
||||||
this.__registers[ 0 ] = str;
|
this.__unnamed( reg );
|
||||||
|
this.__registers[ 0 ] = reg;
|
||||||
};
|
};
|
||||||
|
|
||||||
Registers.prototype.change = function( str )
|
Registers.prototype.change = function( str, newLine )
|
||||||
{
|
{
|
||||||
this.unnamed( str );
|
var reg = new Register( str, newLine );
|
||||||
|
this.__unnamed( reg );
|
||||||
var r = this.__registers;
|
var r = this.__registers;
|
||||||
for( var i = 9; 1 < i; i -- )
|
for( var i = 9; 1 < i; i -- )
|
||||||
{
|
{
|
||||||
@ -43,8 +59,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r[ 1 ] = str;
|
r[ 1 ] = reg;
|
||||||
|
};
|
||||||
|
|
||||||
|
Registers.prototype.get = function( r )
|
||||||
|
{
|
||||||
|
// 0 is one of the registers
|
||||||
|
if( !r && r !== 0 ) r = "\"";
|
||||||
|
|
||||||
|
return this.__registers[ r ];
|
||||||
};
|
};
|
||||||
|
|
||||||
ns[ NS_EXPORT ]( EX_CLASS, "Registers", Registers );
|
ns[ NS_EXPORT ]( EX_CLASS, "Registers", Registers );
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
{
|
{
|
||||||
this.cols = cols;
|
this.cols = cols;
|
||||||
this.statStamp = {};
|
this.statStamp = {};
|
||||||
|
this.override = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
StatusBar.prototype.stamp = function( pos, func )
|
StatusBar.prototype.stamp = function( pos, func )
|
||||||
@ -17,8 +18,12 @@
|
|||||||
this.statStamp[ pos ] = func;
|
this.statStamp[ pos ] = func;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StatusBar.prototype.override;
|
||||||
|
|
||||||
__readOnly( StatusBar.prototype, "statusText", function()
|
__readOnly( StatusBar.prototype, "statusText", function()
|
||||||
{
|
{
|
||||||
|
if( this.override ) return this.override();
|
||||||
|
|
||||||
var display = "";
|
var display = "";
|
||||||
var l = this.cols;
|
var l = this.cols;
|
||||||
|
|
||||||
|
@ -249,15 +249,18 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tMatch = SetParent( tokPairs, highest );
|
if( highest )
|
||||||
var oMatch = tMatch;
|
{
|
||||||
|
var tMatch = SetParent( tokPairs, highest );
|
||||||
|
var oMatch = tMatch;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
oMatch.__open ++;
|
oMatch.__open ++;
|
||||||
oMatch.__close --;
|
oMatch.__close --;
|
||||||
} while( oMatch = oMatch.parent )
|
} while( oMatch = oMatch.parent )
|
||||||
|
|
||||||
if( highest ) return tMatch;
|
return tMatch;
|
||||||
|
}
|
||||||
|
|
||||||
return new TokenMatch();
|
return new TokenMatch();
|
||||||
};
|
};
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
var ns = __namespace( "Components.Vim" );
|
var ns = __namespace( "Components.Vim" );
|
||||||
|
|
||||||
/** @type {Dandelion.IDOMElement} */
|
/** @type {Dandelion.IDOMElement} */
|
||||||
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
||||||
/** @type {System.utils.DataKey} */
|
/** @type {System.utils.DataKey} */
|
||||||
var DataKey = __import( "System.utils.DataKey" );
|
var DataKey = __import( "System.utils.DataKey" );
|
||||||
/** @type {System.Cycle} */
|
/** @type {System.Cycle} */
|
||||||
var Cycle = __import( "System.Cycle" );
|
var Cycle = __import( "System.Cycle" );
|
||||||
/** @type {System.Debug} */
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
/** @type {Components.Vim.State.Registers} */
|
/** @type {Components.Vim.State.Registers} */
|
||||||
var Registers = __import( "Components.Vim.State.Registers" );
|
var Registers = __import( "Components.Vim.State.Registers" );
|
||||||
/** @type {Components.Vim.Syntax.Analyzer} */
|
/** @type {Components.Vim.Syntax.Analyzer} */
|
||||||
var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" );
|
var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" );
|
||||||
|
|
||||||
/** @type {Components.Vim.LineFeeder} */
|
/** @type {Components.Vim.LineFeeder} */
|
||||||
var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
|
var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
|
||||||
@ -96,7 +96,7 @@
|
|||||||
|
|
||||||
// Content feeder
|
// Content feeder
|
||||||
var cfeeder = new LineFeeder( cRange, c );
|
var cfeeder = new LineFeeder( cRange, c );
|
||||||
var contentAnalyzer = new SyntaxAnalyzer( cfeeder );
|
var contentAnalyzer = new SyntaxAnalyzer( cfeeder );
|
||||||
|
|
||||||
// Feed the contents to content feeder
|
// Feed the contents to content feeder
|
||||||
// This "\n" fixes the last line "\n" not displaying
|
// This "\n" fixes the last line "\n" not displaying
|
||||||
@ -104,7 +104,7 @@
|
|||||||
cfeeder.init( content + "\n" );
|
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 );
|
var sfeeder = new LineFeeder( r, c );
|
||||||
sfeeder.setRender( false );
|
sfeeder.setRender( false );
|
||||||
|
|
||||||
// Set the Vim instance
|
// Set the Vim instance
|
||||||
@ -123,9 +123,10 @@
|
|||||||
{
|
{
|
||||||
sfeeder.init( statusBar.statusText );
|
sfeeder.init( statusBar.statusText );
|
||||||
|
|
||||||
|
var sLine = sfeeder.linesOccupied;
|
||||||
element.value =
|
element.value =
|
||||||
cfeeder.render( 0, r - sfeeder.linesOccupied )
|
cfeeder.render( 0, r - sLine )
|
||||||
+ "\n" + sfeeder.render();
|
+ "\n" + sfeeder.render( 0, sLine < r ? sLine : r );
|
||||||
|
|
||||||
_self.__blink = false;
|
_self.__blink = false;
|
||||||
_self.select( cfeeder.cursor.position );
|
_self.select( cfeeder.cursor.position );
|
||||||
@ -135,7 +136,7 @@
|
|||||||
Update();
|
Update();
|
||||||
|
|
||||||
this.contentFeeder = cfeeder;
|
this.contentFeeder = cfeeder;
|
||||||
this.contentAnalyzer = contentAnalyzer;
|
this.contentAnalyzer = contentAnalyzer;
|
||||||
this.statusFeeder = sfeeder;
|
this.statusFeeder = sfeeder;
|
||||||
this.statusBar = statusBar;
|
this.statusBar = statusBar;
|
||||||
this.registers = new Registers();
|
this.registers = new Registers();
|
||||||
|
@ -18,7 +18,12 @@
|
|||||||
, "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"
|
, "LINES_FEWER": "%1 fewer line(s)"
|
||||||
|
, "LINES_MORE": "%1 more line(s)"
|
||||||
|
, "LINES_YANKED": "%1 line(s) yanked"
|
||||||
|
|
||||||
|
, "SEARCH_HIT_BOTTOM": "search hit BOTTOM, continuing at TOP"
|
||||||
|
, "SEARCH_HIT_TOP": "search hit TOP, continuing at BOTTOM"
|
||||||
};
|
};
|
||||||
|
|
||||||
var errors = {
|
var errors = {
|
||||||
|
@ -11,7 +11,11 @@ Components.Vim.Controls.InputEvent.key;
|
|||||||
Components.Vim.Controls.InputEvent.ModKeys;
|
Components.Vim.Controls.InputEvent.ModKeys;
|
||||||
/** @type Boolean */
|
/** @type Boolean */
|
||||||
Components.Vim.Controls.InputEvent.Escape;
|
Components.Vim.Controls.InputEvent.Escape;
|
||||||
|
/** @type Boolean */
|
||||||
|
Components.Vim.Controls.InputEvent.canceled;
|
||||||
/** @type Number */
|
/** @type Number */
|
||||||
Components.Vim.Controls.InputEvent.keyCode;
|
Components.Vim.Controls.InputEvent.keyCode;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.Controls.InputEvent.kMap;
|
Components.Vim.Controls.InputEvent.kMap;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.Controls.InputEvent.cancel;
|
||||||
|
9
botanjs/src/externs/Components.Vim.State.History.js
Normal file
9
botanjs/src/externs/Components.Vim.State.History.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/** @constructor */
|
||||||
|
Components.Vim.State.History = function(){};
|
||||||
|
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.History.push;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.History.prev;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.History.next;
|
@ -5,5 +5,9 @@ Components.Vim.State.Registers = function(){};
|
|||||||
Components.Vim.State.Registers.change;
|
Components.Vim.State.Registers.change;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.State.Registers.yank;
|
Components.Vim.State.Registers.yank;
|
||||||
/** @type Function */
|
|
||||||
Components.Vim.State.Registers.unnamed;
|
/** @constructor */
|
||||||
|
Components.Vim.State.Register = function(){};
|
||||||
|
|
||||||
|
/** @type Boolean */
|
||||||
|
Components.Vim.State.Register.newLine;
|
||||||
|
@ -3,5 +3,7 @@ Components.Vim.StatusBar = function(){};
|
|||||||
|
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.StatusBar.stamp;
|
Components.Vim.StatusBar.stamp;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.StatusBar.override;
|
||||||
/** @type String */
|
/** @type String */
|
||||||
Components.Vim.StatusBar.statusText;
|
Components.Vim.StatusBar.statusText;
|
||||||
|
Loading…
Reference in New Issue
Block a user