AstroJS/botanjs/src/Components/Vim/Actions/FIND.js

171 lines
2.9 KiB
JavaScript

(function(){
var ns = __namespace( "Components.Vim.Actions" );
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
var VimError = __import( "Components.Vim.Error" );
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 ];
if( "nrts.[]()^".indexOf( tok ) != -1 )
{
parsed += "\\" + tok;
}
else
{
throw new Error( "Missing token impl: \"" + tok + "\"" );
}
break;
default:
parsed += pattern[ i ];
}
}
// The root bracket as back ref 0
var RegEx = new RegExp( "(" + parsed + ")", "gm" );
return RegEx;
};
/** @type {Components.Vim.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 )
{
if( p.length < 2 )
{
if( PATTERN.length < 1 )
{
this.__msg = VimError( "E35" );
return true;
}
else p = PATTERN;
}
PATTERN = p;
}
if( PATTERN.length < 1 )
{
this.__msg = VimError( "E35" );
return true;
}
var search;
try
{
search = ParsePattern( PATTERN );
}
catch( ex )
{
this.__msg = VimError( "EX1", ex.message );
return true;
}
var content = this.__cursor.feeder.content;
var cur = this.__cursor;
var p = cur.aPos;
var r;
var Hit;
var FirstHit;
var PrevStack = [];
var LoopGuard;
while( ( r = search.exec( content ) ) !== null )
{
if( FirstHit == undefined )
{
FirstHit = r.index;
}
if( LoopGuard == r.index )
{
this.__msg = VimError( "EX2", PATTERN.slice( 1 ).join( "" ) );
return true;
}
if( p < r.index )
{
Hit = r.index;
break;
}
PrevStack.push( r.index );
LoopGuard = 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 )
{
this.__msg = VimError( "E486", PATTERN.slice( 1 ).join( "" ) );
}
else
{
cur.moveTo( Hit );
}
};
FIND.prototype.getMessage = function()
{
return this.__msg;
};
__static_method( FIND, "Pattern", ParsePattern );
ns[ NS_EXPORT ]( EX_CLASS, "FIND", FIND );
})();