commit bc3c511c6fdc3b61ea7216ab31c427f59e12504c
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2016-03-16T10:55:18Z |
| subject | Fix wrong position of lines with tab character |
commit bc3c511c6fdc3b61ea7216ab31c427f59e12504c
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2016-03-16T10:55:18Z
Fix wrong position of lines with tab character
---
botanjs/src/Components/Vim/Actions/INSERT.js | 100 +++++++++++++++------
botanjs/src/Components/Vim/Actions/UNDO.js | 41 +++++++++
botanjs/src/Components/Vim/Controls.js | 12 ++-
botanjs/src/Components/Vim/Cursor.js | 58 ++++++++++--
botanjs/src/Components/Vim/LineFeeder.js | 2 +-
botanjs/src/Components/Vim/State/Recorder.js | 41 +++++++++
botanjs/src/Components/Vim/State/Stack.js | 19 ++++
botanjs/src/Components/Vim/StatusBar.js | 2 +-
botanjs/src/Components/Vim/_this.js | 2 +
botanjs/src/externs/Components.Vim.Cursor.js | 4 +
.../src/externs/Components.Vim.State.Recorder.js | 9 ++
botanjs/src/externs/Components.Vim.State.Stack.js | 7 ++
botanjs/src/externs/Components.Vim.State.js | 2 +
13 files changed, 263 insertions(+), 36 deletions(-)
diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js
index e131c88..e082baf 100644
--- a/botanjs/src/Components/Vim/Actions/INSERT.js
+++ b/botanjs/src/Components/Vim/Actions/INSERT.js
@@ -1,10 +1,11 @@
(function(){
var ns = __namespace( "Components.Vim.Actions" );
- /** @type {System.Debug} */
- var debug = __import( "System.Debug" );
var Mesg = __import( "Components.Vim.Message" );
+ /** @type {Components.Vim.State.Stack} */
+ var Stack = __import( "Components.Vim.State.Stack" );
+
var Translate = function( 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} */
var INSERT = function( Cursor )
{
/** @type {Components.Vim.Cursor} */
- this.cursor = Cursor;
+ this.__cursor = Cursor;
+
+ // Initialize this stack
+ this.__rec( "", true );
};
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 )
@@ -34,42 +95,27 @@
if( inputChar.length != 1 ) return;
- var cur = this.cursor;
+ var cur = this.__cursor;
var feeder = cur.feeder;
- var line = cur.getLine();
- var n = line.lineNum;
-
- var cont = feeder.content;
+ var f = ContentPosition( feeder );
- var f = 0;
- if( 0 < n )
- {
- f = cont.indexOf( "\n" );
- for( i = 1; f != -1 && i < n; i ++ )
- {
- f = cont.indexOf( "\n", f + 1 );
- }
+ feeder.content =
+ feeder.content.substring( 0, f )
+ + inputChar
+ + feeder.content.substring( f );
- if( this.cursor.feeder.wrap )
- {
- // wordwrap offset
- f ++;
- }
- }
-
- f += cur.aX;
-
- feeder.content = cont.substring( 0, f ) + inputChar + cont.substring( f );
feeder.pan();
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+ this.__rec( inputChar );
+
cur.moveX( 1 );
};
INSERT.prototype.getMessage = function()
{
- var l = this.cursor.feeder.firstBuffer.cols;
+ var l = this.__cursor.feeder.firstBuffer.cols;
var msg = Mesg( "INSERT" );
for( var i = msg.length; i < l; i ++ ) msg += " ";
diff --git a/botanjs/src/Components/Vim/Actions/UNDO.js b/botanjs/src/Components/Vim/Actions/UNDO.js
new file mode 100644
index 0000000..d7a76f8
--- /dev/null
+++ b/botanjs/src/Components/Vim/Actions/UNDO.js
@@ -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 );
+})();
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index 33629ea..7e13dc6 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -62,10 +62,18 @@
case 65: // a
cfeeder.cursor.openAction( "INSERT" );
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
break;
- case 73: // i
+ case 1088: // X, delete before
+ break;
+ case 1085: // U, undo previous changes in oneline
break;
case 1073: // I, append before the line start, after spaces
break;
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index b73c4ed..abb5f1b 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -4,6 +4,9 @@
/** @type {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 GetLine = function( buffs, l )
@@ -71,6 +74,9 @@
// The resulting position
this.P = 0;
+ // State recorder
+ this.rec = new Recorder();
+
this.action = null;
};
@@ -210,6 +216,7 @@
{
if( this.action ) this.action.dispose();
this.action = new (Actions[ name ])( this );
+ this.__pulseMsg = null;
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
};
@@ -219,6 +226,18 @@
if( !this.action ) return;
this.action.dispose();
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" ) );
};
@@ -244,23 +263,52 @@
var X = this.X;
var f = this.feeder;
+ var w = 1;
+
// Calculate wordwrap offset
if( f.wrap )
{
- var cols = f.firstBuffer.cols + 1;
- var w = X < cols ? 0 : Math.floor( X / cols );
+ var lines = this.getLine().visualLines;
- 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()
{
+ if( this.__pulseMsg )
+ {
+ var m = this.__pulseMsg;
+ this.__pulseMsg = null;
+
+ return m;
+ }
+
return this.action && this.action.getMessage();
} );
diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
index 059fd04..58258b4 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -195,7 +195,7 @@
} );
__readOnly( Feeder.prototype, "lineStat", function() {
- var X = this.cursor.aX;
+ var X = this.cursor.aX + 1;
var line = this.cursor.getLine();
var tabStat = "";
diff --git a/botanjs/src/Components/Vim/State/Recorder.js b/botanjs/src/Components/Vim/State/Recorder.js
new file mode 100644
index 0000000..e6cfe6b
--- /dev/null
+++ b/botanjs/src/Components/Vim/State/Recorder.js
@@ -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 );
+})();
diff --git a/botanjs/src/Components/Vim/State/Stack.js b/botanjs/src/Components/Vim/State/Stack.js
new file mode 100644
index 0000000..a58e99d
--- /dev/null
+++ b/botanjs/src/Components/Vim/State/Stack.js
@@ -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 );
+})();
diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js
index c02f82c..1a57d5c 100644
--- a/botanjs/src/Components/Vim/StatusBar.js
+++ b/botanjs/src/Components/Vim/StatusBar.js
@@ -32,7 +32,7 @@
if( text == undefined || text === "" ) continue;
display += text.substr( 0, avail );
- i = display.length - 1;
+ i = display.length;
}
else display += " ";
}
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 0ed8cd0..b568ced 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -13,6 +13,8 @@
, "BOTTOM": "Bot"
, "ALL": "All"
, "EXIT": "Type :quit<Enter> to exit Vim"
+
+ , "UNDO_LIMIT": "Already at oldest change"
};
var errors = {
diff --git a/botanjs/src/externs/Components.Vim.Cursor.js b/botanjs/src/externs/Components.Vim.Cursor.js
index 4564825..13b5624 100644
--- a/botanjs/src/externs/Components.Vim.Cursor.js
+++ b/botanjs/src/externs/Components.Vim.Cursor.js
@@ -5,6 +5,8 @@ Components.Vim.Cursor = function(){};
Components.Vim.Cursor.feeder;
/** @type {Components.Vim.IAction} */
Components.Vim.Cursor.action;
+/** @type {Components.Vim.State.Recorder} */
+Components.Vim.Cursor.rec;
/** @type Function */
Components.Vim.Cursor.moveX;
@@ -19,6 +21,8 @@ Components.Vim.Cursor.updatePosition;
/** @type Function */
Components.Vim.Cursor.openAction;
/** @type Function */
+Components.Vim.Cursor.openRunAction;
+/** @type Function */
Components.Vim.Cursor.closeAction;
/** @type {Array} */
diff --git a/botanjs/src/externs/Components.Vim.State.Recorder.js b/botanjs/src/externs/Components.Vim.State.Recorder.js
new file mode 100644
index 0000000..0303938
--- /dev/null
+++ b/botanjs/src/externs/Components.Vim.State.Recorder.js
@@ -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;
diff --git a/botanjs/src/externs/Components.Vim.State.Stack.js b/botanjs/src/externs/Components.Vim.State.Stack.js
new file mode 100644
index 0000000..c572081
--- /dev/null
+++ b/botanjs/src/externs/Components.Vim.State.Stack.js
@@ -0,0 +1,7 @@
+/** @constructor */
+Components.Vim.State.Stack = function(){};
+
+/** @type Function */
+Components.Vim.State.Stack.play;
+/** @type Function */
+Components.Vim.State.Stack.store;
diff --git a/botanjs/src/externs/Components.Vim.State.js b/botanjs/src/externs/Components.Vim.State.js
new file mode 100644
index 0000000..884e6dc
--- /dev/null
+++ b/botanjs/src/externs/Components.Vim.State.js
@@ -0,0 +1,2 @@
+/** @object */
+Components.Vim.State = {};