History stacks

This commit is contained in:
斟酌 鵬兄 2016-04-02 18:35:12 +08:00
parent c7249c071c
commit 3ed7d2be84
6 changed files with 212 additions and 33 deletions

View File

@ -4,8 +4,8 @@
/** @type {System.Debug} */ /** @type {System.Debug} */
var debug = __import( "System.Debug" ); var debug = __import( "System.Debug" );
/** @type {Components.Vim.Ex.Search} */ /** @type {Components.Vim.Ex.Command} */
var ExSearch = __import( "Components.Vim.Ex.Search" ); var ExCommand = __import( "Components.Vim.Ex.Command" );
var beep = ns[ NS_INVOKE ]( "Beep" ); var beep = ns[ NS_INVOKE ]( "Beep" );
@ -441,10 +441,10 @@
}, _8 ); }, _8 );
break; break;
case SLASH: // "/" Seach movement case SLASH: // "/" Search movement
this.__cMovement = true; this.__cMovement = true;
this.__divedCCmd = new ExSearch( ccur ); this.__divedCCmd = new ExCommand( ccur, "/" );
this.__divedCCmd.handler( e ); this.__divedCCmd.handler( e );
break; break;
default: default:
@ -499,7 +499,8 @@
this.__cMovement = false; this.__cMovement = false;
this.__divedCCmd = null; this.__divedCCmd = null;
} }
else return;
if( e.canceled ) return;
} }
var cfeeder = this.__cfeeder; var cfeeder = this.__cfeeder;
@ -545,6 +546,7 @@
var InputEvent = function( sender, e ) var InputEvent = function( sender, e )
{ {
this.__target = sender; this.__target = sender;
this.__canceled = false;
if( typeof( e ) == "string" ) if( typeof( e ) == "string" )
{ {
@ -572,11 +574,14 @@
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() {

View File

@ -8,25 +8,35 @@
/** @type {System.utils.Perf} */ /** @type {System.utils.Perf} */
var Perf = __import( "System.utils.Perf" ); var Perf = __import( "System.utils.Perf" );
/**j@type {Components.Vim.State.History} */
var History = __import( "Components.Vim.State.History" );
var Mesg = __import( "Components.Vim.Message" ); 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} */ /** @type {Components.Vim.Cursor.IAction} */
var Search = function( Cursor ) var Command = function( Cursor, Mode )
{ {
var _self = this; var _self = this;
if( !ZMap[ Mode ] ) throw new Error( "Unsupport mode: " + Mode );
/** @type {Components.Vim.Cursor} */ /** @type {Components.Vim.Cursor} */
this.__cursor = Cursor; this.__cursor = Cursor;
this.__statusBar = Cursor.Vim.statusBar; this.__statusBar = Cursor.Vim.statusBar;
this.__command = []; this.__mode = Mode;
this.__blinkId = "ExSearchBlinkCycle" + Perf.uuid; this.__hist = new History( ZMap[ Mode ] );
this.__curPos = 0;
this.__disp = function() this.__command = [];
{ this.__currentCommand = null;
}; this.__blinkId = "ExCommandBlinkCycle" + Perf.uuid;
this.__curPos = 0;
var feeder = Cursor.feeder; var feeder = Cursor.feeder;
@ -77,7 +87,7 @@
this.__statusBar.override = this.__doBlink; this.__statusBar.override = this.__doBlink;
}; };
Search.prototype.dispose = function() Command.prototype.dispose = function()
{ {
this.__statusBar.override = null; this.__statusBar.override = null;
@ -86,7 +96,7 @@
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) ); feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
}; };
Search.prototype.handler = function( e ) Command.prototype.handler = function( e )
{ {
e.preventDefault(); e.preventDefault();
@ -96,6 +106,8 @@
var InputKey = null; var InputKey = null;
var histNav = false;
if( e.kMap( "Tab" ) ) if( e.kMap( "Tab" ) )
{ {
InputKey = "^I"; InputKey = "^I";
@ -106,8 +118,15 @@
} }
else if( e.kMap( "BS" ) ) else if( e.kMap( "BS" ) )
{ {
if( this.__curPos == 1 && 1 < this.__command.length )
return false;
this.__command.splice( --this.__curPos, 1 ); this.__command.splice( --this.__curPos, 1 );
if( this.__command.length == 0 ) return true; if( this.__command.length == 0 )
{
e.cancel();
return true;
}
} }
else if( e.kMap( "Del" ) ) else if( e.kMap( "Del" ) )
{ {
@ -115,23 +134,56 @@
} }
else if( e.kMap( "Enter" ) ) else if( e.kMap( "Enter" ) )
{ {
this.__process();
return true; return true;
} }
else if( e.kMap( "Up" ) ) // History navigations
{
}
else if( e.kMap( "Down" ) )
{
}
else if( e.kMap( "Left" ) ) else if( e.kMap( "Left" ) )
{ {
if( 0 < this.__curPos ) this.__curPos --; if( 1 < this.__curPos ) this.__curPos --;
} }
else if( e.kMap( "Right" ) ) else if( e.kMap( "Right" ) )
{ {
if( this.__curPos < this.__command.length ) if( this.__curPos < this.__command.length )
this.__curPos ++; 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 else
{ {
InputKey = e.key; InputKey = e.key;
@ -142,9 +194,22 @@
this.__command.splice( this.__curPos ++, 0, InputKey ); this.__command.splice( this.__curPos ++, 0, InputKey );
} }
var feeder = this.__cursor.feeder; if( !histNav )
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) ); {
this.__hist.reset();
if( this.__currentCommand ) this.__currentCommand = this.__command;
} }
ns[ NS_EXPORT ]( EX_CLASS, "Search", Search ); e.cancel();
var feeder = this.__cursor.feeder;
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
};
Command.prototype.__process = function()
{
this.__hist.push( this.__command );
};
ns[ NS_EXPORT ]( EX_CLASS, "Command", Command );
})(); })();

View 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 );
})();

View File

@ -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;

View 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;