forked from Botanical/BotanJS
Merge remote-tracking branch 'vim/master' into Astro
This commit is contained in:
commit
ae6048ecb1
@ -1,10 +1,11 @@
|
|||||||
(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" );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.State.Stack} */
|
||||||
|
var Stack = __import( "Components.Vim.State.Stack" );
|
||||||
|
|
||||||
var Translate = function( c )
|
var Translate = function( c )
|
||||||
{
|
{
|
||||||
switch( c )
|
switch( c )
|
||||||
@ -16,15 +17,75 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* @param {Components.Vim.LineFeeder} */
|
||||||
|
var ContentPosition = function( f )
|
||||||
|
{
|
||||||
|
var line = f.cursor.getLine();
|
||||||
|
var n = line.lineNum;
|
||||||
|
|
||||||
|
var p = 0;
|
||||||
|
if( 0 < n )
|
||||||
|
{
|
||||||
|
p = f.content.indexOf( "\n" );
|
||||||
|
for( i = 1; p != -1 && i < n; i ++ )
|
||||||
|
{
|
||||||
|
p = f.content.indexOf( "\n", p + 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( f.wrap )
|
||||||
|
{
|
||||||
|
// wordwrap offset
|
||||||
|
p ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p += f.cursor.aX;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
|
||||||
/** @type {Components.Vim.Cursor.IAction} */
|
/** @type {Components.Vim.Cursor.IAction} */
|
||||||
var INSERT = function( Cursor )
|
var INSERT = function( Cursor )
|
||||||
{
|
{
|
||||||
/** @type {Components.Vim.Cursor} */
|
/** @type {Components.Vim.Cursor} */
|
||||||
this.cursor = Cursor;
|
this.__cursor = Cursor;
|
||||||
|
|
||||||
|
// Initialize this stack
|
||||||
|
this.__rec( "", true );
|
||||||
};
|
};
|
||||||
|
|
||||||
INSERT.prototype.dispose = function()
|
INSERT.prototype.dispose = function()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
INSERT.prototype.__storeState = function( c, pos )
|
||||||
|
{
|
||||||
|
return function() {
|
||||||
|
debug.Inf( pos, c );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
INSERT.prototype.__rec = function( c, newRec )
|
||||||
|
{
|
||||||
|
if( newRec || !this.__stack )
|
||||||
|
{
|
||||||
|
if( this.__stack )
|
||||||
|
{
|
||||||
|
var c = this.__content;
|
||||||
|
|
||||||
|
this.__stack.store(
|
||||||
|
this.__storeState( c, this.__startPosition )
|
||||||
|
);
|
||||||
|
|
||||||
|
this.__cursor.rec.store( this.__stack );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__content = "";
|
||||||
|
this.__stack = new Stack();
|
||||||
|
this.__startPosition = ContentPosition( this.__cursor.feeder );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.__content += c;
|
||||||
};
|
};
|
||||||
|
|
||||||
INSERT.prototype.handler = function( e )
|
INSERT.prototype.handler = function( e )
|
||||||
@ -34,42 +95,27 @@
|
|||||||
|
|
||||||
if( inputChar.length != 1 ) return;
|
if( inputChar.length != 1 ) return;
|
||||||
|
|
||||||
var cur = this.cursor;
|
var cur = this.__cursor;
|
||||||
var feeder = cur.feeder;
|
var feeder = cur.feeder;
|
||||||
|
|
||||||
var line = cur.getLine();
|
var f = ContentPosition( feeder );
|
||||||
var n = line.lineNum;
|
|
||||||
|
|
||||||
var cont = feeder.content;
|
feeder.content =
|
||||||
|
feeder.content.substring( 0, f )
|
||||||
|
+ inputChar
|
||||||
|
+ feeder.content.substring( f );
|
||||||
|
|
||||||
var f = 0;
|
|
||||||
if( 0 < n )
|
|
||||||
{
|
|
||||||
f = cont.indexOf( "\n" );
|
|
||||||
for( i = 1; f != -1 && i < n; i ++ )
|
|
||||||
{
|
|
||||||
f = cont.indexOf( "\n", f + 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( this.cursor.feeder.wrap )
|
|
||||||
{
|
|
||||||
// wordwrap offset
|
|
||||||
f ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
f += cur.aX;
|
|
||||||
|
|
||||||
feeder.content = cont.substring( 0, f ) + inputChar + cont.substring( f );
|
|
||||||
feeder.pan();
|
feeder.pan();
|
||||||
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
|
|
||||||
|
this.__rec( inputChar );
|
||||||
|
|
||||||
cur.moveX( 1 );
|
cur.moveX( 1 );
|
||||||
};
|
};
|
||||||
|
|
||||||
INSERT.prototype.getMessage = function()
|
INSERT.prototype.getMessage = function()
|
||||||
{
|
{
|
||||||
var l = this.cursor.feeder.firstBuffer.cols;
|
var l = this.__cursor.feeder.firstBuffer.cols;
|
||||||
var msg = Mesg( "INSERT" );
|
var msg = Mesg( "INSERT" );
|
||||||
|
|
||||||
for( var i = msg.length; i < l; i ++ ) msg += " ";
|
for( var i = msg.length; i < l; i ++ ) msg += " ";
|
||||||
|
41
botanjs/src/Components/Vim/Actions/UNDO.js
Normal file
41
botanjs/src/Components/Vim/Actions/UNDO.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.Actions" );
|
||||||
|
|
||||||
|
var Mesg = __import( "Components.Vim.Message" );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.Cursor.IAction} */
|
||||||
|
var UNDO = function( Cursor )
|
||||||
|
{
|
||||||
|
/** @type {Components.Vim.Cursor} */
|
||||||
|
this.__cursor = Cursor;
|
||||||
|
this.__message = "UNDO COMMAND";
|
||||||
|
};
|
||||||
|
|
||||||
|
UNDO.prototype.dispose = function()
|
||||||
|
{
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
UNDO.prototype.handler = function( e )
|
||||||
|
{
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
/** @type {Components.Vim.State.Stack} */
|
||||||
|
var stack = this.__cursor.rec.undo();
|
||||||
|
if( stack )
|
||||||
|
{
|
||||||
|
stack.play();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.__message = Mesg( "UNDO_LIMIT" );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
UNDO.prototype.getMessage = function()
|
||||||
|
{
|
||||||
|
return this.__message;
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "UNDO", UNDO );
|
||||||
|
})();
|
@ -62,10 +62,18 @@
|
|||||||
case 65: // a
|
case 65: // a
|
||||||
cfeeder.cursor.openAction( "INSERT" );
|
cfeeder.cursor.openAction( "INSERT" );
|
||||||
break;
|
break;
|
||||||
|
case 73: // i
|
||||||
|
break;
|
||||||
|
case 85: // u, undo
|
||||||
|
cfeeder.cursor.openRunAction( "UNDO", e );
|
||||||
|
break;
|
||||||
|
case 88: // x, del
|
||||||
|
break;
|
||||||
case 1065: // A, append at the line end
|
case 1065: // A, append at the line end
|
||||||
break;
|
break;
|
||||||
case 73: // i
|
case 1088: // X, delete before
|
||||||
|
break;
|
||||||
|
case 1085: // U, undo previous changes in oneline
|
||||||
break;
|
break;
|
||||||
case 1073: // I, append before the line start, after spaces
|
case 1073: // I, append before the line start, after spaces
|
||||||
break;
|
break;
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
/** @type {System.Debug} */
|
/** @type {System.Debug} */
|
||||||
var debug = __import( "System.Debug" );
|
var debug = __import( "System.Debug" );
|
||||||
|
|
||||||
|
/** @type {Components.Vim.State.Recorder} */
|
||||||
|
var Recorder = __import( "Components.Vim.State.Recorder" );
|
||||||
|
|
||||||
var Actions = __import( "Components.Vim.Actions.*" );
|
var Actions = __import( "Components.Vim.Actions.*" );
|
||||||
|
|
||||||
var GetLine = function( buffs, l )
|
var GetLine = function( buffs, l )
|
||||||
@ -71,6 +74,9 @@
|
|||||||
// The resulting position
|
// The resulting position
|
||||||
this.P = 0;
|
this.P = 0;
|
||||||
|
|
||||||
|
// State recorder
|
||||||
|
this.rec = new Recorder();
|
||||||
|
|
||||||
this.action = null;
|
this.action = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -210,6 +216,7 @@
|
|||||||
{
|
{
|
||||||
if( this.action ) this.action.dispose();
|
if( this.action ) this.action.dispose();
|
||||||
this.action = new (Actions[ name ])( this );
|
this.action = new (Actions[ name ])( this );
|
||||||
|
this.__pulseMsg = null;
|
||||||
|
|
||||||
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
};
|
};
|
||||||
@ -219,6 +226,18 @@
|
|||||||
if( !this.action ) return;
|
if( !this.action ) return;
|
||||||
this.action.dispose();
|
this.action.dispose();
|
||||||
this.action = null;
|
this.action = null;
|
||||||
|
this.__pulseMsg = null;
|
||||||
|
|
||||||
|
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
|
};
|
||||||
|
|
||||||
|
Cursor.prototype.openRunAction = function( name, e )
|
||||||
|
{
|
||||||
|
/** @type {Components.Vim.IAction} */
|
||||||
|
var action = new (Actions[ name ])( this );
|
||||||
|
action.handler( e );
|
||||||
|
this.__pulseMsg = action.getMessage();
|
||||||
|
action.dispose();
|
||||||
|
|
||||||
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
||||||
};
|
};
|
||||||
@ -244,23 +263,52 @@
|
|||||||
var X = this.X;
|
var X = this.X;
|
||||||
var f = this.feeder;
|
var f = this.feeder;
|
||||||
|
|
||||||
|
var w = 1;
|
||||||
|
|
||||||
// Calculate wordwrap offset
|
// Calculate wordwrap offset
|
||||||
if( f.wrap )
|
if( f.wrap )
|
||||||
{
|
{
|
||||||
var cols = f.firstBuffer.cols + 1;
|
var lines = this.getLine().visualLines;
|
||||||
var w = X < cols ? 0 : Math.floor( X / cols );
|
|
||||||
|
|
||||||
if( 0 < w )
|
for( var i in lines )
|
||||||
{
|
{
|
||||||
X -= w;
|
/** @type {Components.Vim.LineBuffer} */
|
||||||
|
var vline = lines[ i ];
|
||||||
|
|
||||||
|
// Actual length
|
||||||
|
var aLen = vline.content.toString().length;
|
||||||
|
|
||||||
|
// Visual length
|
||||||
|
var vLen = vline.toString().length;
|
||||||
|
|
||||||
|
// Plus the "\n" character
|
||||||
|
X -= vLen + 1;
|
||||||
|
|
||||||
|
if( 0 <= X )
|
||||||
|
{
|
||||||
|
w += aLen;
|
||||||
|
}
|
||||||
|
else if( X < 0 )
|
||||||
|
{
|
||||||
|
w += X + vLen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return X;
|
return w;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
__readOnly( Cursor.prototype, "message", function()
|
__readOnly( Cursor.prototype, "message", function()
|
||||||
{
|
{
|
||||||
|
if( this.__pulseMsg )
|
||||||
|
{
|
||||||
|
var m = this.__pulseMsg;
|
||||||
|
this.__pulseMsg = null;
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
return this.action && this.action.getMessage();
|
return this.action && this.action.getMessage();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
__readOnly( Feeder.prototype, "lineStat", function() {
|
__readOnly( Feeder.prototype, "lineStat", function() {
|
||||||
var X = this.cursor.aX;
|
var X = this.cursor.aX + 1;
|
||||||
var line = this.cursor.getLine();
|
var line = this.cursor.getLine();
|
||||||
var tabStat = "";
|
var tabStat = "";
|
||||||
|
|
||||||
|
41
botanjs/src/Components/Vim/State/Recorder.js
Normal file
41
botanjs/src/Components/Vim/State/Recorder.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.State" );
|
||||||
|
|
||||||
|
var Recorder = function()
|
||||||
|
{
|
||||||
|
this.__steps = [];
|
||||||
|
this.__i = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Recorder.prototype.undo = function()
|
||||||
|
{
|
||||||
|
var i = this.__i - 1;
|
||||||
|
if( i == -1 || !this.__steps.length ) return null;
|
||||||
|
|
||||||
|
|
||||||
|
return this.__steps[ this.__i = i ];
|
||||||
|
};
|
||||||
|
|
||||||
|
Recorder.prototype.redo = function()
|
||||||
|
{
|
||||||
|
var i = this.__i + 1;
|
||||||
|
if( i == -1 || !this.__steps.length ) return null;
|
||||||
|
|
||||||
|
var State = this.__steps[ i ];
|
||||||
|
if( State )
|
||||||
|
{
|
||||||
|
this.__i = i;
|
||||||
|
return State;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
Recorder.prototype.record = function( StateObj )
|
||||||
|
{
|
||||||
|
this.__steps[ this.__i ] = StateObj;
|
||||||
|
delete this.__steps[ ++ this.__i ];
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "Recorder", Recorder );
|
||||||
|
})();
|
19
botanjs/src/Components/Vim/State/Stack.js
Normal file
19
botanjs/src/Components/Vim/State/Stack.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
(function(){
|
||||||
|
var ns = __namespace( "Components.Vim.State" );
|
||||||
|
|
||||||
|
var Stack = function()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
Stack.prototype.store = function( handler )
|
||||||
|
{
|
||||||
|
this.__handler = handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
Stack.prototype.play = function()
|
||||||
|
{
|
||||||
|
if( this.__handler ) this.__handler();
|
||||||
|
};
|
||||||
|
|
||||||
|
ns[ NS_EXPORT ]( EX_CLASS, "Stack", Stack );
|
||||||
|
})();
|
@ -32,7 +32,7 @@
|
|||||||
if( text == undefined || text === "" ) continue;
|
if( text == undefined || text === "" ) continue;
|
||||||
|
|
||||||
display += text.substr( 0, avail );
|
display += text.substr( 0, avail );
|
||||||
i = display.length - 1;
|
i = display.length;
|
||||||
}
|
}
|
||||||
else display += " ";
|
else display += " ";
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
, "BOTTOM": "Bot"
|
, "BOTTOM": "Bot"
|
||||||
, "ALL": "All"
|
, "ALL": "All"
|
||||||
, "EXIT": "Type :quit<Enter> to exit Vim"
|
, "EXIT": "Type :quit<Enter> to exit Vim"
|
||||||
|
|
||||||
|
, "UNDO_LIMIT": "Already at oldest change"
|
||||||
};
|
};
|
||||||
|
|
||||||
var errors = {
|
var errors = {
|
||||||
|
@ -5,6 +5,8 @@ Components.Vim.Cursor = function(){};
|
|||||||
Components.Vim.Cursor.feeder;
|
Components.Vim.Cursor.feeder;
|
||||||
/** @type {Components.Vim.IAction} */
|
/** @type {Components.Vim.IAction} */
|
||||||
Components.Vim.Cursor.action;
|
Components.Vim.Cursor.action;
|
||||||
|
/** @type {Components.Vim.State.Recorder} */
|
||||||
|
Components.Vim.Cursor.rec;
|
||||||
|
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.Cursor.moveX;
|
Components.Vim.Cursor.moveX;
|
||||||
@ -19,6 +21,8 @@ Components.Vim.Cursor.updatePosition;
|
|||||||
/** @type Function */
|
/** @type Function */
|
||||||
Components.Vim.Cursor.openAction;
|
Components.Vim.Cursor.openAction;
|
||||||
/** @type Function */
|
/** @type Function */
|
||||||
|
Components.Vim.Cursor.openRunAction;
|
||||||
|
/** @type Function */
|
||||||
Components.Vim.Cursor.closeAction;
|
Components.Vim.Cursor.closeAction;
|
||||||
|
|
||||||
/** @type {Array} */
|
/** @type {Array} */
|
||||||
|
9
botanjs/src/externs/Components.Vim.State.Recorder.js
Normal file
9
botanjs/src/externs/Components.Vim.State.Recorder.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/** @constructor */
|
||||||
|
Components.Vim.State.Recorder = function(){};
|
||||||
|
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.undo;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.redo;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.record;
|
7
botanjs/src/externs/Components.Vim.State.Stack.js
Normal file
7
botanjs/src/externs/Components.Vim.State.Stack.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/** @constructor */
|
||||||
|
Components.Vim.State.Stack = function(){};
|
||||||
|
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.Stack.play;
|
||||||
|
/** @type Function */
|
||||||
|
Components.Vim.State.Stack.store;
|
2
botanjs/src/externs/Components.Vim.State.js
Normal file
2
botanjs/src/externs/Components.Vim.State.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/** @object */
|
||||||
|
Components.Vim.State = {};
|
Loading…
Reference in New Issue
Block a user