From a927c901345730e8053cea9ec89cc27e9f910d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=9F=E9=85=8C=20=E9=B5=AC=E5=85=84?= Date: Fri, 1 Apr 2016 04:05:43 +0800 Subject: [PATCH] Rewrite moveX function --- botanjs/src/Components/Vim/Actions/PUT.js | 8 ++- botanjs/src/Components/Vim/Actions/VISUAL.js | 18 +++-- botanjs/src/Components/Vim/Controls.js | 9 +++ botanjs/src/Components/Vim/Cursor.js | 73 +++++++++++++++++--- botanjs/src/Components/Vim/LineBuffer.js | 11 ++- 5 files changed, 101 insertions(+), 18 deletions(-) diff --git a/botanjs/src/Components/Vim/Actions/PUT.js b/botanjs/src/Components/Vim/Actions/PUT.js index 81ff721..2dbb263 100644 --- a/botanjs/src/Components/Vim/Actions/PUT.js +++ b/botanjs/src/Components/Vim/Actions/PUT.js @@ -44,9 +44,13 @@ var feeder = cur.feeder; var newLine = cput.newLine; + + // Compensation + var c = e.kMap( "P" ) ? 0 : -1; + if( newLine ) { - cur.moveY( 1 ); + cur.moveY( -c ); cur.lineStart(); } @@ -69,7 +73,7 @@ stack.store( function() { f(); - cur.moveY( -1 ); + cur.moveY( c ); } ); } else diff --git a/botanjs/src/Components/Vim/Actions/VISUAL.js b/botanjs/src/Components/Vim/Actions/VISUAL.js index caac607..060cdbf 100644 --- a/botanjs/src/Components/Vim/Actions/VISUAL.js +++ b/botanjs/src/Components/Vim/Actions/VISUAL.js @@ -36,10 +36,20 @@ VISUAL.prototype.dispose = function() { this.__msg = this.__leaveMesg; - this.__cursor.blink = true; - this.__cursor.pSpace = false; - this.__cursor.PStart = this.__selStart; - this.__cursor.PEnd = this.__selStart + 1; + var c = this.__cursor; + + c.blink = true; + c.pSpace = false; + c.PStart = this.__selStart; + c.PEnd = this.__selStart + 1; + + // This fix the highlighting position of missing phantomSpace + // for maximum filled line + if( c.feeder.wrap ) + { + c.moveX( -1 ); + c.moveX( 1 ); + } }; VISUAL.prototype.handler = function( e, done ) diff --git a/botanjs/src/Components/Vim/Controls.js b/botanjs/src/Components/Vim/Controls.js index 1163433..8dc0ac3 100644 --- a/botanjs/src/Components/Vim/Controls.js +++ b/botanjs/src/Components/Vim/Controls.js @@ -396,6 +396,7 @@ }, _8 ); break; + case SLASH: // "/" Seach movement case SLASH: // "/" Seach movement this.__cMovement = true; break; @@ -443,7 +444,15 @@ else { if( ccur.action.allowMovement ) + { + var SubCommand = !this.__compositeReg; this.__cursorCommand( e, kCode ); + if( SubCommand && this.__compositeReg ) + { + e.preventDefault(); + return; + } + } if( ccur.action.handler( e ) ) { diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js index 3f884cc..3c4927f 100644 --- a/botanjs/src/Components/Vim/Cursor.js +++ b/botanjs/src/Components/Vim/Cursor.js @@ -83,6 +83,9 @@ this.pSpace = false; this.__suppEvt = 0; + + // Offset compensation for max filled wrapped line + this.__off = 0; }; // Set by VimArea @@ -118,6 +121,8 @@ var jumpY = expLineNum - lastLineNum; var jumpX = aPos < lineStart ? lineStart - aPos : aPos - lineStart; + jumpX += Math.ceil( jumpX / pline.cols ) - 1; + if( jumpY ) this.moveY( jumpY ); if( 0 < this.getLine().lineNum && lineStart <= aPos ) jumpX --; @@ -130,13 +135,19 @@ Cursor.prototype.moveX = function( d, penetrate, phantomSpace ) { var x = this.pX; + if( 0 < this.__off ) + { + d += this.__off; + this.__off = 0; + } var updatePx = Boolean( d ); if( updatePx ) x = this.X + d; if( !d ) d = 1; - var buffs = this.feeder.lineBuffers; + var feeder = this.feeder; + var buffs = feeder.lineBuffers; if( penetrate ) { @@ -153,23 +164,61 @@ var content = line.visualLines.join( "\n" ); var cLen = content.length; + var lineEnd = 0; + var hasPhantomSpace = true; + + // Empty lines has length of 1 + // If length larger than a, need to compensate the lineEnd + // for phantomSpace + if( 1 < cLen ) + { + // Begin check if whether this line contains phantomSpace + var lineNum = line.lineNum - 1; + var str = feeder.content; + for( var i = str.indexOf( "\n" ), j = 0; 0 <= i; i = str.indexOf( "\n", i ), j ++ ) + { + if( lineNum == j ) break; + i ++; + } + + if( j == 0 && i == -1 ) i = 0; + + var end = str.indexOf( "\n", i + 1 ); + end = end == -1 ? str.length : end; + + // Actual LineLength + var hasPhantomSpace = 0 < ( end - i - 1 ) % line.cols; + + if( hasPhantomSpace ) + { + lineEnd = phantomSpace ? cLen - 1 : cLen - 2; + } + else + { + lineEnd = phantomSpace ? cLen : cLen - 1; + } + } + var c = content[ x ]; - // Motion includes empty lines before cursor end - if( ( phantomSpace && cLen - 1 <= x ) || ( cLen == 1 && c == undefined ) ) + // Whether x is at line boundary + var boundary = c == undefined || ( cLen == x + 1 && c == " " ); + + if( boundary ) { - x = 0 < d ? cLen - 1 : 0; - } - // ( 2 < cLen ) motion excludes empty lines at cursor end - else if( ( 2 <= cLen && x == cLen - 1 && c == " " ) || c == undefined ) - { - x = 0 < d ? cLen - 2 : 0; + x = 0 < d ? lineEnd : 0; } else if( c == "\n" ) { x += d; } + // Wordwrap phantomSpace movement compensation on max filled lines + if( feeder.wrap && boundary && !hasPhantomSpace && phantomSpace ) + { + this.__off = 1; + } + this.X = x; if( updatePx ) @@ -177,6 +226,7 @@ this.pX = x; this.updatePosition(); } + }; Cursor.prototype.lineStart = function() @@ -193,10 +243,11 @@ Cursor.prototype.updatePosition = function() { - var P = this.X + LineOffset( this.feeder.lineBuffers, this.Y ); + var feeder = this.feeder; + var P = this.X + LineOffset( feeder.lineBuffers, this.Y ) + this.__off; + this.PStart = P; this.PEnd = P + 1; - this.__p = P; this.__visualUpdate(); }; diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js index 238cfb3..e097f83 100644 --- a/botanjs/src/Components/Vim/LineBuffer.js +++ b/botanjs/src/Components/Vim/LineBuffer.js @@ -3,6 +3,8 @@ var debug = __import( "System.Debug" ); + var occurence = __import( "System.utils.Perf.CountSubstr" ); + var LineBuffer = function( cols, nextLineBuffer ) { this.prev = null; @@ -60,6 +62,12 @@ line += c; } + + if( !br && i == this.cols && content[i] == "\n" ) + { + i ++; + br = true; + } } else { @@ -97,7 +105,8 @@ LineBuffer.prototype.toString = function() { - if( this.content.length < this.cols ) + var c = this.cols - occurence( this.content, "\t" ) * ( this.tabWidth - 1 ); + if( this.content.length < c ) { return this.content + " "; }