commit 42bbc3b24046f5134c96860cff1a5a4a778ac164
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2017-01-25T03:04:29Z |
| subject | Fixed cursor mis-positioned on tab characters |
commit 42bbc3b24046f5134c96860cff1a5a4a778ac164
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2017-01-25T03:04:29Z
Fixed cursor mis-positioned on tab characters
---
botanjs/src/Components/Vim/Actions/INSERT.js | 6 +-
botanjs/src/Components/Vim/Actions/SHIFT_LINES.js | 2 +-
botanjs/src/Components/Vim/Actions/VISUAL.js | 4 +-
botanjs/src/Components/Vim/Controls.js | 18 +++--
botanjs/src/Components/Vim/Cursor.js | 81 ++++++++++++++++++++---
botanjs/src/Components/Vim/_this.js | 2 +-
6 files changed, 90 insertions(+), 23 deletions(-)
diff --git a/botanjs/src/Components/Vim/Actions/INSERT.js b/botanjs/src/Components/Vim/Actions/INSERT.js
index 4beaca5..bec9396 100644
--- a/botanjs/src/Components/Vim/Actions/INSERT.js
+++ b/botanjs/src/Components/Vim/Actions/INSERT.js
@@ -60,7 +60,7 @@
}
this.__msg = "";
this.__rec( "", true );
- this.__cursor.moveX( -1 );
+ this.__cursor.moveX( -1, false, false, true );
};
INSERT.prototype.__rec = function( c, newRec )
@@ -197,7 +197,7 @@
{
this.__realizeIndent();
feeder.pan();
- cur.moveX( inputChar == "\t" ? feeder.firstBuffer.tabWidth : 1, false, true );
+ cur.moveX( inputChar == "\t" ? feeder.firstBuffer.tabWidth : 1, false, true, true );
}
feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
@@ -262,7 +262,7 @@
feeder.softReset();
feeder.pan();
- cur.moveX( i * feeder.firstBuffer.tabWidth, false, true );
+ cur.moveX( i, false, true );
var a = [];
a[ IN_START ] = f;
diff --git a/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js b/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
index 0e83a39..606e17d 100644
--- a/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
+++ b/botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
@@ -345,7 +345,7 @@
f();
// Offset correction after REDO / UNDO
cur.moveTo( recStart );
- cur.lineStart();
+ cur.lineStart( true );
} );
cur.moveTo( recStart );
diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js
index 55aa192..3bdb8d3 100644
--- a/botanjs/src/Components/Vim/Actions/VISUAL.js
+++ b/botanjs/src/Components/Vim/Actions/VISUAL.js
@@ -220,13 +220,13 @@
if( cur.aPos == startLine.aPos )
{
- cur.moveTo( r.open, true );
+ cur.moveTo( r.open, true, false, true );
this.__reset( cur );
startLine = this.__startLine;
}
cur.unsuppressEvent();
- cur.moveTo( r.close, true );
+ cur.moveTo( r.close, true, false, true );
}
var currAp = cur.aPos;
diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js
index cdb320c..0c34dcc 100644
--- a/botanjs/src/Components/Vim/Controls.js
+++ b/botanjs/src/Components/Vim/Controls.js
@@ -259,9 +259,17 @@
{
case SHIFT + A: // Append at the line end
ccur.lineEnd();
- case A: // Append
- ccur.moveX( 1, true, true );
+ ccur.moveX( 1, true, true, true );
+ ccur.openAction( "INSERT", e );
+ break;
case I: // Insert
+ ccur.moveX( -1 );
+ case A: // Append
+ ccur.moveX( 1, true, true, true );
+ ccur.openAction( "INSERT", e );
+ break;
+ case SHIFT + I: // Append at line start
+ ccur.lineStart( true );
ccur.openAction( "INSERT", e );
break;
@@ -515,11 +523,11 @@
case SHIFT + L: // Last line buffer
break;
- case _0: // Really - line Start
+ case _0: // Really line Start
ccur.lineStart();
break;
- case SHIFT + _6: // ^, line Start, XXX: skip tabs
- ccur.lineStart();
+ case SHIFT + _6: // ^, line Start at word
+ ccur.lineStart( true );
break;
case SHIFT + _4: // $, End
ccur.lineEnd( ccur.pSpace );
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index 810bf70..e59b69d 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -103,7 +103,7 @@
Cursor.prototype.Vim;
// Move to an absolute position
- Cursor.prototype.moveTo = function( aPos, phantomSpace )
+ Cursor.prototype.moveTo = function( aPos, phantomSpace, skipTabs )
{
var content = this.feeder.content;
var pline = this.getLine();
@@ -133,19 +133,18 @@
var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart;
jumpX += Math.ceil( jumpX / pline.cols ) - 1;
- jumpX += occurence( content.substring( lineStart + 1, aPos ), "\t" ) * ( pline.tabWidth - 1 );
if( jumpY ) this.moveY( jumpY );
// This is needed because first line does not contain the first "\n" character
if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --;
- this.moveX( - Number.MAX_VALUE );
- this.moveX( jumpX, false, phantomSpace );
+ this.moveX( - Number.MAX_VALUE, false, false, true );
+ this.moveX( jumpX, false, phantomSpace, skipTabs );
};
// 0 will be treated as default ( 1 )
- Cursor.prototype.moveX = function( d, penetrate, phantomSpace )
+ Cursor.prototype.moveX = function( d, penetrate, phantomSpace, skipTab )
{
var x = this.pX;
var updatePx = Boolean( d );
@@ -177,6 +176,8 @@
/** @type {Components.Vim.LineBuffer} */
var line = this.getLine();
+ var tabStep = line.tabWidth - 1;
+ var rline = this.rawLine;
var content = line.visualLines.join( "\n" );
var cLen = content.length;
@@ -190,8 +191,7 @@
{
// Begin check if this line contains phantomSpace
// hasPhantomSpace = 0 < ( rawLine.displayLength ) % cols
- var rline = this.rawLine;
- hasPhantomSpace = 0 < ( rline.length + occurence( rline, "\t" ) * ( line.tabWidth - 1 ) ) % line.cols;
+ hasPhantomSpace = 0 < ( rline.length + occurence( rline, "\t" ) * tabStep ) % line.cols;
if( hasPhantomSpace )
{
@@ -203,6 +203,56 @@
}
}
+ // Hacky tab compensations
+ if( !skipTab )
+ {
+ var s = this.aX;
+ var a = rline[ s + d ];
+ var e = s;
+ if( d < 0 )
+ {
+ if( rline[ s ] == "\t" )
+ {
+ x -= tabStep;
+ if( x < 0 )
+ x = tabStep;
+ }
+
+ s += d;
+
+ var ntabs = occurence( rline.substring( s, e ), "\t" ) - 1;
+ if( 0 < ntabs ) x -= ntabs * tabStep;
+ }
+ else if( updatePx ) // && 0 < d ( assuming d can never be 0 )
+ {
+ // Going from one line to next
+ // linebreaks are *invisible*
+ var isLF = ( content[ x ] == "\n" ) ? 1 : 0;
+
+ if( s == 0 )
+ {
+ x = 1;
+ if ( rline[ 0 ] == "\t" )
+ {
+ x += tabStep;
+ }
+ }
+
+ e += d;
+
+ var ntabs = occurence( rline.substring( s + 1, e + 1 ), "\t" );
+ x += ntabs * tabStep + isLF;
+ if( 1 < d ) x += d - 1;
+ }
+ else // jk, non-X navigation. i.e., pX does not change
+ {
+ // s = 0, which is unused here
+ e = x + d;
+ x += ( occurence( rline.substring( 0, e ), "\t" ) ) * tabStep;
+ if( 1 < d ) x += d - 1;
+ }
+ }
+
var c = content[ x ];
// Whether x is at line boundary
@@ -227,22 +277,31 @@
if( updatePx )
{
- this.pX = x;
+ this.pX = this.aX;
this.updatePosition();
}
};
- Cursor.prototype.lineStart = function()
+ Cursor.prototype.lineStart = function( atWord )
{
- this.pX = 0;
+ if( atWord )
+ {
+ var a = this.rawLine.match( /^[ \t]+/g );
+ this.pX = a ? a[0].length : 0;
+ }
+ else
+ {
+ this.pX = 0;
+ }
+
this.moveX();
this.updatePosition();
};
Cursor.prototype.lineEnd = function( phantomSpace )
{
- this.moveX( Number.MAX_VALUE, false, phantomSpace );
+ this.moveX( Number.MAX_VALUE, false, phantomSpace, true );
};
Cursor.prototype.updatePosition = function()
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index bfa1b4b..e00d556 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -6,7 +6,7 @@ VIMRE_VERSION = "1.0.0b";
"INSERT": "-- INSERT --"
, "REPLACE": "-- REPLACE --"
, "MORE": "-- MORE --"
- , "VISUAL": "-- VISUAL --"
+ , "VISUAL": "-- VISUAL --"
, "VISLINE": "-- VISUAL LINE --"
, "REGISTERS": "--- Registers ---"
, "WRITE": "\"%1\" %2L, %3C written"