forked from Botanical/BotanJS
History stacks
This commit is contained in:
parent
c7249c071c
commit
3ed7d2be84
@ -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() {
|
||||||
|
|
||||||
|
@ -8,27 +8,37 @@
|
|||||||
/** @type {System.utils.Perf} */
|
/** @type {System.utils.Perf} */
|
||||||
var Perf = __import( "System.utils.Perf" );
|
var Perf = __import( "System.utils.Perf" );
|
||||||
|
|
||||||
var Mesg = __import( "Components.Vim.Message" );
|
/**j@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} */
|
/** @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.__mode = Mode;
|
||||||
|
this.__hist = new History( ZMap[ Mode ] );
|
||||||
|
|
||||||
this.__command = [];
|
this.__command = [];
|
||||||
this.__blinkId = "ExSearchBlinkCycle" + Perf.uuid;
|
this.__currentCommand = null;
|
||||||
|
this.__blinkId = "ExCommandBlinkCycle" + Perf.uuid;
|
||||||
this.__curPos = 0;
|
this.__curPos = 0;
|
||||||
|
|
||||||
this.__disp = function()
|
var feeder = Cursor.feeder;
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
var feeder = Cursor.feeder;
|
|
||||||
|
|
||||||
var __blink = false;
|
var __blink = false;
|
||||||
var __holdBlink = false;
|
var __holdBlink = false;
|
||||||
@ -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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !histNav )
|
||||||
|
{
|
||||||
|
this.__hist.reset();
|
||||||
|
if( this.__currentCommand ) this.__currentCommand = this.__command;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.cancel();
|
||||||
|
|
||||||
var feeder = this.__cursor.feeder;
|
var feeder = this.__cursor.feeder;
|
||||||
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
}
|
};
|
||||||
|
|
||||||
ns[ NS_EXPORT ]( EX_CLASS, "Search", Search );
|
Command.prototype.__process = function()
|
||||||
|
{
|
||||||
|
this.__hist.push( this.__command );
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "Command", Command );
|
||||||
})();
|
})();
|
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 );
|
||||||
|
})();
|
@ -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
|
||||||
@ -136,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();
|
||||||
|
@ -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;
|
Loading…
Reference in New Issue
Block a user