commit 2548970f3a77df69da1f463514dfdaa2e7beb7f3
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2016-03-13T12:26:26Z |
| subject | Partial nav of "jkhl$^" |
commit 2548970f3a77df69da1f463514dfdaa2e7beb7f3
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2016-03-13T12:26:26Z
Partial nav of "jkhl$^"
---
botanjs/src/Components/Vim/Cursor.js | 51 ++++++++++-------
botanjs/src/Components/Vim/LineBuffer.js | 2 +-
botanjs/src/Components/Vim/LineFeeder.js | 96 +++++++++++++++++++++++---------
botanjs/src/Components/Vim/VimArea.js | 27 ++++++++-
botanjs/src/Components/Vim/_this.js | 1 +
5 files changed, 127 insertions(+), 50 deletions(-)
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
index b72ea1b..4ce90fa 100644
--- a/botanjs/src/Components/Vim/Cursor.js
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -37,42 +37,39 @@
/** @type {Components.Vim.LineBuffer} */
var offset = 0;
+ LineLoop:
for( var i = 0, line = buffs[0];
line && i < l; i ++ )
{
while( line )
{
- if( line.br )
- {
- offset += line.prev.toString().length + 1;
-
- // Empty line has a special space
- if( line.content == "" ) offset ++;
+ if( line.next && line.next.placeholder )
+ break LineLoop;
+ if( line.next && line.next.br )
+ {
+ offset += line.toString().length + 1;
line = line.next;
break;
}
else
{
- if( offset == 0 ) offset -= 1;
-
- if( line.next && !line.next.br )
- offset += line.cols + 1;
+ offset += line.cols + 1;
}
line = line.next;
}
}
- debug.Info( offset );
-
return offset;
};
- var Cursor = function( buffs )
+ var Cursor = function( feeder )
{
- this.buffers = buffs;
- this.cols = buffs[0].cols;
+ /** @type {Components.Vim.LineFeeder} */
+ this.feeder = feeder;
+
+ this.cols = feeder.lineBuffers[0].cols;
// The preferred X position
this.pX = 0;
@@ -98,7 +95,7 @@
if( !d ) d = 1;
- var buffs = this.buffers;
+ var buffs = this.feeder.lineBuffers;
/** @type {Components.Vim.LineBuffer} */
var line = GetLine( buffs, this.Y );
@@ -133,18 +130,34 @@
Cursor.prototype.lineEnd = function()
{
- /** @type {Components.Vim.LineBuffer} */
this.moveX( Number.MAX_VALUE );
};
Cursor.prototype.updatePosition = function()
{
- this.P = this.X + LineOffset( this.buffers, this.Y );
+ this.P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
};
Cursor.prototype.moveY = function( d )
{
- this.Y += d;
+ var Y = this.Y;
+
+ Y += d;
+ if( Y < 0 ) Y = 0;
+
+ if( this.feeder.moreAt < Y )
+ {
+ this.feeder.pan( undefined, Y - this.feeder.moreAt );
+
+ // Keep original position after panning
+ this.moveX();
+ this.updatePosition();
+ this.refresh();
+ return;
+ }
+
+ this.Y = Y;
+
this.moveX();
this.updatePosition();
};
diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js
index aa0360a..ff54620 100644
--- a/botanjs/src/Components/Vim/LineBuffer.js
+++ b/botanjs/src/Components/Vim/LineBuffer.js
@@ -24,7 +24,6 @@
{
nextLineBuffer.prev = this;
}
-
};
LineBuffer.prototype.Push = function( content, wrap )
@@ -32,6 +31,7 @@
if( content == undefined || content === "" )
{
this.content = "~";
+ this.br = true;
this.placeholder = true;
if( this.next ) this.next.Push( content, wrap );
return;
diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
index 2aba1f8..7725443 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -29,10 +29,18 @@
lineBuffers[i] = new LineBuffer( cols, lineBuffers[ i + 1 ] );
}
- this.cursor = new Cursor( lineBuffers );
-
this.lineBuffers = lineBuffers;
+
+ this.panX = 0;
+ this.panY = 0;
+
this.setRender();
+
+ this.cursor = new Cursor( this );
+ this.dispatcher = new EventDispatcher();
+
+ this.__clseLine = null;
+ this.__moreAt = -1;
};
Feeder.prototype.init = function( content, wrap )
@@ -52,38 +60,35 @@
{
if( placeholder == undefined ) placeholder = true;
- if( placeholder )
- {
- this.__render = function( line, steps )
- {
- var display = ( line == undefined ? "" : line ) + "";
+ var _self = this;
- for( var i = 0;
- line && i < steps && ( line = line.next );
- i ++ )
- {
- display += "\n" + line;
- }
+ var placeholdCond = placeholder
+ ? function( line ) { return true; }
+ : function( line ) { return !line.placeholder; }
+ ;
- return display;
- };
- }
- else
+ this.__render = function( line, steps )
{
- this.__render = function( line, steps )
- {
- var display = ( line == undefined ? "" : line ) + "";
+ var display = ( line == undefined ? "" : line ) + "";
- for( var i = 0;
- line && i < steps && ( line = line.next ) && !line.placeholder;
- i ++ )
+ var atSpace = false
+ for( var i = 0;
+ line && i < steps && ( line = line.next ) && placeholdCond( line );
+ i ++ )
+ {
+ if( atSpace || ( line.br && steps < ( i + line.visualLines.length ) ) )
{
- display += "\n" + line;
+ if( !atSpace ) _self.__clseLine = line;
+ atSpace = true;
+ display += "\n@";
+ continue;
}
- return display;
- };
- }
+ display += "\n" + line;
+ }
+
+ return display;
+ };
}
Feeder.prototype.render = function( start, length )
@@ -101,6 +106,43 @@
return this.__render( buffs[ start ], length - 1 );
};
+ Feeder.prototype.pan = function( dX, dY )
+ {
+ if( dX == undefined ) dX = 0;
+ if( dY == undefined ) dY = 0;
+
+ var X = this.panX + dX;
+ var Y = this.panY + dY;
+
+ // this.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
+ };
+
+ __readOnly( Feeder.prototype, "moreAt", function() {
+ if( 0 < this.__moreAt ) return this.__moreAt;
+
+ var line = this.lineBuffers[0];
+ if( line.placeholder ) return 0;
+
+ var i = 0;
+ do
+ {
+ if( this.__clseLine == line ) break;
+ if( line.br ) i ++;
+ }
+ while( line = line.next );
+
+ return ( this.__moreAt = i );
+ } );
+
+ __readOnly( Feeder.prototype, "lineStat", function() {
+ var X = this.cursor.X;
+ return ( this.cursor.Y + this.panY + 1 ) + "," + X + "-" + ( X );
+ } );
+
+ __readOnly( Feeder.prototype, "docPos", function() {
+ return "Top";
+ } );
+
__readOnly( Feeder.prototype, "linesOccupied", function() {
var line = this.lineBuffers[0];
if( line.placeholder ) return 0;
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 159a34f..0cea4d7 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -52,6 +52,7 @@
{
// Cursor movements
case 72: // h
+ case 8: // Backspace
cfeeder.cursor.moveX( -1 );
break;
case 74: // j
@@ -86,6 +87,14 @@
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 );
};
@@ -112,7 +121,13 @@
this.PosX = 1;
this.PosY = 1;
+ this.__active = false;
+
+ var _self = this;
+
stage.addEventListener( "KeyDown", KeyHandler( this, VimControls ) );
+ stage.addEventListener( "Focus", function() { _self.__active = true; } );
+ stage.addEventListener( "Blur", function() { _self.__active = false; } );
// Init
this.content = element.value;
@@ -125,6 +140,7 @@
VimArea.prototype.select = function( sel )
{
+ if( !this.__active ) return;
var textarea = this.stage.element;
if( sel )
@@ -154,12 +170,12 @@
// XXX: Placeholder
var statusBar = new StatusBar( c );
statusBar.stamp( -18, function(){
- return "1,1-1";
+ return cfeeder.lineStat;
});
statusBar.stamp( -3, function(){
- return "All";
- });
+ return cfeeder.docPos;
+ } );
sfeeder.init( statusBar.statusText );
@@ -167,8 +183,13 @@
cfeeder.render( 0, r - sfeeder.linesOccupied )
+ "\n" + sfeeder.render();
+ cfeeder.dispatcher.addEventListener( "VisualUpdate", function()
+ {
+ } );
+
this.contentFeeder = cfeeder;
this.statusFeeder = sfeeder;
+ this.statusBar = statusBar;
this.__cursor = cfeeder.cursor;
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 5de456f..d61f8fc 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -16,6 +16,7 @@
"INSERT": "-- INSERT --"
, "REPLACE": "-- REPLACE --"
, "MORE": "-- MORE --"
+ , "VISLINE": "-- VISUAL LINE --"
, "WRITE": "\"%1\" %2L, %3C written"
, "CONTINUE": "Press ENTER or type command to continue"
, "SEARCH_HIT_BOTTOM": "Seach hit BOTTOM, contining at TOP"