From bd35ed56b1ab9e605eea45b57becec6956178ada 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: Mon, 14 Mar 2016 02:15:24 +0800 Subject: [PATCH] j for collapsed line ( partial ) --- botanjs/src/Components/Vim/Cursor.js | 55 +++++++++++++++--- botanjs/src/Components/Vim/LineBuffer.js | 14 +++-- botanjs/src/Components/Vim/LineFeeder.js | 74 ++++++++++++++++++------ botanjs/src/Components/Vim/StatusBar.js | 3 +- botanjs/src/Components/Vim/VimArea.js | 44 +++++++------- botanjs/src/Components/Vim/_this.js | 20 ++++++- 6 files changed, 154 insertions(+), 56 deletions(-) diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js index 4ce90fa..0fb6284 100644 --- a/botanjs/src/Components/Vim/Cursor.js +++ b/botanjs/src/Components/Vim/Cursor.js @@ -69,7 +69,7 @@ /** @type {Components.Vim.LineFeeder} */ this.feeder = feeder; - this.cols = feeder.lineBuffers[0].cols; + this.cols = feeder.firstBuffer.cols; // The preferred X position this.pX = 0; @@ -136,6 +136,7 @@ Cursor.prototype.updatePosition = function() { this.P = this.X + LineOffset( this.feeder.lineBuffers, this.Y ); + this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) ); }; Cursor.prototype.moveY = function( d ) @@ -143,16 +144,42 @@ var Y = this.Y; Y += d; - if( Y < 0 ) Y = 0; - - if( this.feeder.moreAt < Y ) + if( Y < 0 ) { - this.feeder.pan( undefined, Y - this.feeder.moreAt ); + Y = 0; + } + else if( this.feeder.moreAt < Y ) + { + var feeder = this.feeder; + var lastLine = feeder.lastBuffer.lineNum; + var i = 0; + while( true ) + { + feeder.pan( undefined, Y - feeder.moreAt + i ); + + // If it is the same line we keep scrolling it + // until the entire line cosumes the screen + if( feeder.lastBuffer.lineNum == lastLine ) + { + i ++; + } + else break; + } + + for( i = 0, line = feeder.firstBuffer; + line != feeder.lastBuffer; + line = line.next ) + { + if( line.br ) i ++; + if( line.lineNum == Y ) break; + } + + this.Y = i; // Keep original position after panning this.moveX(); this.updatePosition(); - this.refresh(); + return; } @@ -162,6 +189,21 @@ this.updatePosition(); }; + Cursor.prototype.getLine = function() + { + var feeder = this.feeder; + var line = feeder.firstBuffer; + for( var i = 0; + line != feeder.lastBuffer; + line = line.next ) + { + if( line.br ) i ++; + if( this.Y == i ) break; + } + + return line; + }; + __readOnly( Cursor.prototype, "position", function() { return { @@ -170,6 +212,5 @@ }; } ); - ns[ NS_EXPORT ]( EX_CLASS, "Cursor", Cursor ); })(); diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js index ff54620..ed612a6 100644 --- a/botanjs/src/Components/Vim/LineBuffer.js +++ b/botanjs/src/Components/Vim/LineBuffer.js @@ -19,6 +19,7 @@ this.next = nextLineBuffer; this.br = false; this.placeholder = true; + this.lineNum = 0; if( nextLineBuffer ) { @@ -26,14 +27,15 @@ } }; - LineBuffer.prototype.Push = function( content, wrap ) + LineBuffer.prototype.Push = function( content, wrap, n ) { + this.lineNum = n; if( content == undefined || content === "" ) { this.content = "~"; this.br = true; this.placeholder = true; - if( this.next ) this.next.Push( content, wrap ); + if( this.next ) this.next.Push( content, wrap, n + 1 ); return; } @@ -42,9 +44,10 @@ var line = ""; var br = false; + var i = 0; if( wrap ) { - for( var i = 0; i < this.cols; i ++ ) + for( ; i < this.cols; i ++ ) { var c = content[i]; if( c === undefined ) break; @@ -62,7 +65,7 @@ else { br = true; - for( var i = 0; true; i ++ ) + for( ; true; i ++ ) { var c = content[i]; if( c === undefined ) break; @@ -83,7 +86,7 @@ if( this.next ) { this.next.br = br; - this.next.Push( content.substr( i ), wrap ); + this.next.Push( content.substr( i ), wrap, br ? n + 1 : n ); } this.content = line; @@ -106,6 +109,5 @@ return lines; } ); - ns[ NS_EXPORT ]( EX_CLASS, "LineBuffer", LineBuffer ); })(); diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js index 7725443..3edc1b7 100644 --- a/botanjs/src/Components/Vim/LineFeeder.js +++ b/botanjs/src/Components/Vim/LineFeeder.js @@ -21,12 +21,12 @@ { var lineBuffers = []; - // Last line - lineBuffers[ rows - 1 ] = new LineBuffer( cols ); + // Last line, hidden buffer that won't be rendered + this.__xBuffer = lineBuffers[ rows ] = new LineBuffer( cols ); - for( var i = rows - 2; 0 <= i; i -- ) + for( var i = rows - 1; 0 <= i; i -- ) { - lineBuffers[i] = new LineBuffer( cols, lineBuffers[ i + 1 ] ); + lineBuffers[ i ] = new LineBuffer( cols, lineBuffers[ i + 1 ] ); } this.lineBuffers = lineBuffers; @@ -41,19 +41,23 @@ this.__clseLine = null; this.__moreAt = -1; + this.__rows = rows; + + this.__wrap = true; }; Feeder.prototype.init = function( content, wrap ) { - if( wrap == undefined ) wrap = true; - if( this.lineBuffers.length ) - { - this.lineBuffers[0].Push( content, wrap ); - } + this.content = content; + this.setWrap( wrap ); + + this.firstBuffer.Push( content, this.__wrap, 0 ); }; - Feeder.prototype.wrap = function( setwrap ) + Feeder.prototype.setWrap = function( wrap ) { + if( wrap == undefined ) return; + this.__wrap = wrap; }; Feeder.prototype.setRender = function( placeholder ) @@ -96,10 +100,10 @@ var buffs = this.lineBuffers; if( start == undefined ) start = 0; - else if( buffs.length < start ) return ""; + else if( this.__rows < start ) return ""; - if( length == undefined || ( buffs.length - start ) < length ) - length = buffs.length - start; + if( length == undefined || ( this.__rows - start ) < length ) + length = this.rows - start; if( length == 0 ) return ""; @@ -111,16 +115,40 @@ if( dX == undefined ) dX = 0; if( dY == undefined ) dY = 0; + if( dX == 0 && dY == 0 ) return; + var X = this.panX + dX; var Y = this.panY + dY; - // this.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) ); + var f = this.content.indexOf( "\n" ); + var i = 1; + + while( f != - 1 && i < Y ) + { + i ++; + f = this.content.indexOf( "\n", f + 1 ); + } + + this.firstBuffer.Push( + this.content.substr( f + 1 ) + , this.__wrap, i ); + + this.panX = X; + this.panY = Y; }; + __readOnly( Feeder.prototype, "firstBuffer", function() { + return this.lineBuffers[ 0 ]; + } ); + + __readOnly( Feeder.prototype, "lastBuffer", function() { + return this.lineBuffers[ this.__rows - 1 ]; + } ); + __readOnly( Feeder.prototype, "moreAt", function() { if( 0 < this.__moreAt ) return this.__moreAt; - var line = this.lineBuffers[0]; + var line = this.firstBuffer; if( line.placeholder ) return 0; var i = 0; @@ -136,15 +164,25 @@ __readOnly( Feeder.prototype, "lineStat", function() { var X = this.cursor.X; - return ( this.cursor.Y + this.panY + 1 ) + "," + X + "-" + ( X ); + return ( this.cursor.getLine().lineNum + 1 ) + "," + X + "-" + ( X ); } ); __readOnly( Feeder.prototype, "docPos", function() { - return "Top"; + var pos = "ALL"; + + if( this.panY == 0 ) + { + if( this.__clseLine || !this.EOF ) + { + pos = "TOP"; + } + } + + return pos; } ); __readOnly( Feeder.prototype, "linesOccupied", function() { - var line = this.lineBuffers[0]; + var line = this.firstBuffer; if( line.placeholder ) return 0; var i = 0; diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js index 9aa4535..20424c8 100644 --- a/botanjs/src/Components/Vim/StatusBar.js +++ b/botanjs/src/Components/Vim/StatusBar.js @@ -1,4 +1,5 @@ -(function(){ var ns = __namespace( "Components.Vim" ); +(function(){ + var ns = __namespace( "Components.Vim" ); /** @type {Dandelion} */ var Dand = __import( "Dandelion" ); diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js index 0cea4d7..bf3105b 100644 --- a/botanjs/src/Components/Vim/VimArea.js +++ b/botanjs/src/Components/Vim/VimArea.js @@ -19,6 +19,8 @@ /** @type {Components.Vim.StatusBar} */ var StatusBar = ns[ NS_INVOKE ]( "StatusBar" ); + var mesg = ns[ NS_INVOKE ]( "Message" ); + var KeyHandler = function( sender, handler ) { return function( e ) @@ -87,16 +89,6 @@ case 112: // F1, help } - var sfeeder = sender.statusFeeder; - var statusBar = sender.statusBar; - - sfeeder.init( statusBar.statusText ); - sender.stage.element.value = - cfeeder.render( 0, sender.rows - sfeeder.linesOccupied ) - + "\n" + sfeeder.render(); - - sender.__blink = false; - sender.select( cfeeder.cursor.position ); }; /* stage @param {Dandelion.IDOMElement} */ @@ -130,8 +122,7 @@ stage.addEventListener( "Blur", function() { _self.__active = false; } ); // Init - this.content = element.value; - this.VisualizeVimFrame(); + this.VisualizeVimFrame( element.value ); }; VimArea.prototype.startInput = function( mode ) @@ -150,7 +141,7 @@ } }; - VimArea.prototype.VisualizeVimFrame = function() + VimArea.prototype.VisualizeVimFrame = function( content ) { var _self = this; @@ -161,7 +152,7 @@ // Content feeder var cfeeder = new LineFeeder( r, c ); - cfeeder.init( this.content ); + cfeeder.init( content ); // Status feeder sfeeder = new LineFeeder( r, c ); @@ -174,18 +165,25 @@ }); statusBar.stamp( -3, function(){ - return cfeeder.docPos; + return mesg( cfeeder.docPos ); } ); sfeeder.init( statusBar.statusText ); - element.value = - cfeeder.render( 0, r - sfeeder.linesOccupied ) - + "\n" + sfeeder.render(); - - cfeeder.dispatcher.addEventListener( "VisualUpdate", function() + var Update = function() { - } ); + sfeeder.init( statusBar.statusText ); + + element.value = + cfeeder.render( 0, r - sfeeder.linesOccupied ) + + "\n" + sfeeder.render(); + + _self.__blink = false; + _self.select( cfeeder.cursor.position ); + }; + + cfeeder.dispatcher.addEventListener( "VisualUpdate", Update ); + Update(); this.contentFeeder = cfeeder; this.statusFeeder = sfeeder; @@ -204,5 +202,9 @@ }, 600 ); }; + __readOnly( VimArea.prototype, "content", function() { + return this.contentFeeder.content; + } ); + ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea ); })(); diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js index d61f8fc..d45751f 100644 --- a/botanjs/src/Components/Vim/_this.js +++ b/botanjs/src/Components/Vim/_this.js @@ -30,15 +30,29 @@ "E486": "E486: Pattern not found: %1" }; - var Message = function( key ) + var GetString = function( arr, key, restArgs ) { - var restArgs = Array.prototype.slice.apply( arguments, 1 ); + if( arr[ key ] == undefined ) return key; + var i = 0; - return messages[ key ].replace( /%\d+/g, function( e ) + return arr[ key ].replace( /%\d+/g, function( e ) { return restArgs[ i ++ ]; } ); }; + var Message = function( key ) + { + var restArgs = Array.prototype.slice.call( arguments, 1 ); + return GetString( messages, key, restArgs ); + }; + + var Error = function( key ) + { + var restArgs = Array.prototype.slice.call( arguments, 1 ); + return GetString( errors, key, restArgs ); + }; + ns[ NS_EXPORT ]( EX_FUNC, "Message", Message ); + ns[ NS_EXPORT ]( EX_FUNC, "Error", Error ); })();