commit 751530b42d7ea237677ac3333fc28b9fd42cab12
| author | 斟酌 鵬兄 <tgckpg@gmail.com> |
| date | 2016-03-13T00:35:29Z |
| subject | Some navigation, but not working:( |
commit 751530b42d7ea237677ac3333fc28b9fd42cab12
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date: 2016-03-13T00:35:29Z
Some navigation, but not working:(
---
botanjs/src/Components/Vim/Cursor.js | 162 +++++++++++++++++++++++++++++++
botanjs/src/Components/Vim/LineBuffer.js | 111 +++++++++++++++++++++
botanjs/src/Components/Vim/LineFeeder.js | 118 ++++------------------
botanjs/src/Components/Vim/VimArea.js | 94 +++++++++++-------
botanjs/src/Components/Vim/_this.js | 1 +
5 files changed, 352 insertions(+), 134 deletions(-)
diff --git a/botanjs/src/Components/Vim/Cursor.js b/botanjs/src/Components/Vim/Cursor.js
new file mode 100644
index 0000000..b72ea1b
--- /dev/null
+++ b/botanjs/src/Components/Vim/Cursor.js
@@ -0,0 +1,162 @@
+(function(){
+ var ns = __namespace( "Components.Vim" );
+
+ /** @type {Dandelion} */
+ var Dand = __import( "Dandelion" );
+ /** @type {Dandelion.IDOMElement} */
+ var IDOMElement = __import( "Dandelion.IDOMElement" );
+ /** @type {Dandelion.IDOMObject} */
+ var IDOMObject = __import( "Dandelion.IDOMObject" );
+ /** @type {System.Cycle} */
+ var Cycle = __import( "System.Cycle" );
+ /** @type {System.Debug} */
+ var debug = __import( "System.Debug" );
+
+ var GetLine = function( buffs, l )
+ {
+ /** @type {Components.Vim.LineBuffer} */
+ var LineHead = buffs[0];
+ l ++;
+
+ for( var i = 0, line = LineHead;
+ line && i < l; i ++ )
+ {
+ LineHead = line;
+ while( line )
+ {
+ line = line.next;
+ if( line.br ) break;
+ }
+ }
+
+ return LineHead;
+ };
+
+ var LineOffset = function( buffs, l )
+ {
+ /** @type {Components.Vim.LineBuffer} */
+ var offset = 0;
+
+ 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 ++;
+
+ line = line.next;
+ break;
+ }
+ else
+ {
+ if( offset == 0 ) offset -= 1;
+
+ if( line.next && !line.next.br )
+ offset += line.cols + 1;
+ }
+
+ line = line.next;
+ }
+ }
+
+ debug.Info( offset );
+
+ return offset;
+ };
+
+ var Cursor = function( buffs )
+ {
+ this.buffers = buffs;
+ this.cols = buffs[0].cols;
+
+ // The preferred X position
+ this.pX = 0;
+
+ // The displaying X position
+ this.X = 0;
+
+ // The current line resided
+ this.Y = 0;
+
+ // The resulting position
+ this.P = 0;
+ };
+
+ // Can only be 1, -1
+ // 0 will be treated as undefined
+ Cursor.prototype.moveX = function( d )
+ {
+ var x = this.pX;
+
+ var updatePx = Boolean( d );
+ if( updatePx ) x = this.X + d;
+
+ if( !d ) d = 1;
+
+ var buffs = this.buffers;
+
+ /** @type {Components.Vim.LineBuffer} */
+ var line = GetLine( buffs, this.Y );
+ var content = line.visualLines.join( "\n" );
+
+ var c = content[ x ];
+
+ if( c == undefined )
+ {
+ x = d > 0 ? content.length - 1 : 0;
+ }
+ else if( c == "\n" )
+ {
+ x += d;
+ }
+
+ this.X = x;
+
+ if( updatePx )
+ {
+ this.pX = x;
+ this.updatePosition();
+ }
+ };
+
+ Cursor.prototype.lineStart = function()
+ {
+ this.pX = 0;
+ this.moveX();
+ this.updatePosition();
+ };
+
+ 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 );
+ };
+
+ Cursor.prototype.moveY = function( d )
+ {
+ this.Y += d;
+ this.moveX();
+ this.updatePosition();
+ };
+
+ __readOnly( Cursor.prototype, "position", function()
+ {
+ return {
+ start: this.P
+ , end: this.P + 1
+ };
+ } );
+
+
+ ns[ NS_EXPORT ]( EX_CLASS, "Cursor", Cursor );
+})();
diff --git a/botanjs/src/Components/Vim/LineBuffer.js b/botanjs/src/Components/Vim/LineBuffer.js
new file mode 100644
index 0000000..aa0360a
--- /dev/null
+++ b/botanjs/src/Components/Vim/LineBuffer.js
@@ -0,0 +1,111 @@
+(function(){
+ var ns = __namespace( "Components.Vim" );
+
+ /** @type {Dandelion} */
+ var Dand = __import( "Dandelion" );
+ /** @type {Dandelion.IDOMElement} */
+ var IDOMElement = __import( "Dandelion.IDOMElement" );
+ /** @type {Dandelion.IDOMObject} */
+ var IDOMObject = __import( "Dandelion.IDOMObject" );
+ /** @type {System.Cycle} */
+ var Cycle = __import( "System.Cycle" );
+ /** @type {System.Debug} */
+ var debug = __import( "System.Debug" );
+
+ var LineBuffer = function( cols, nextLineBuffer )
+ {
+ this.prev = null;
+ this.cols = cols;
+ this.next = nextLineBuffer;
+ this.br = false;
+ this.placeholder = true;
+
+ if( nextLineBuffer )
+ {
+ nextLineBuffer.prev = this;
+ }
+
+ };
+
+ LineBuffer.prototype.Push = function( content, wrap )
+ {
+ if( content == undefined || content === "" )
+ {
+ this.content = "~";
+ this.placeholder = true;
+ if( this.next ) this.next.Push( content, wrap );
+ return;
+ }
+
+ this.placeholder = false;
+
+ var line = "";
+ var br = false;
+
+ if( wrap )
+ {
+ for( var i = 0; i < this.cols; i ++ )
+ {
+ var c = content[i];
+ if( c === undefined ) break;
+
+ if( c == "\n" )
+ {
+ br = true;
+ i ++;
+ break;
+ }
+
+ line += c;
+ }
+ }
+ else
+ {
+ br = true;
+ for( var i = 0; true; i ++ )
+ {
+ var c = content[i];
+ if( c === undefined ) break;
+
+ if( c == "\n" )
+ {
+ i ++;
+ break;
+ }
+
+ if( i < this.cols )
+ {
+ line += c;
+ }
+ }
+ }
+
+ if( this.next )
+ {
+ this.next.br = br;
+ this.next.Push( content.substr( i ), wrap );
+ }
+
+ this.content = line;
+ };
+
+ LineBuffer.prototype.toString = function()
+ {
+ return this.content || " ";
+ };
+
+ __readOnly( LineBuffer.prototype, "visualLines", function()
+ {
+ var lines = [ this ];
+ var line = this;
+ while( ( line = line.next ) && !line.br )
+ {
+ lines.push( line );
+ }
+
+ 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 ae8af80..2aba1f8 100644
--- a/botanjs/src/Components/Vim/LineFeeder.js
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -12,111 +12,38 @@
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
- var Line = function( cols, nextLine )
- {
- this.cols = cols;
- this.next = nextLine;
- this.br = false;
- this.placeholder = true;
- };
-
- Line.prototype.Push = function( content, wrap )
- {
- if( content == undefined || content === "" )
- {
- this.content = "~";
- this.placeholder = true;
- if( this.next ) this.next.Push( content, wrap );
- return;
- }
-
- this.placeholder = false;
-
- var line = "";
- var br = false;
-
- if( wrap )
- {
- for( var i = 0; i < this.cols; i ++ )
- {
- var c = content[i];
- if( c === undefined ) break;
-
- if( c == "\n" )
- {
- br = true;
- i ++;
- break;
- }
-
- line += c;
- }
- }
- else
- {
- br = true;
- for( var i = 0; true; i ++ )
- {
- var c = content[i];
- if( c === undefined ) break;
-
- if( c == "\n" )
- {
- i ++;
- break;
- }
-
- if( i < this.cols )
- {
- line += c;
- }
- }
- }
-
- if( this.next )
- {
- this.next.br = br;
- this.next.Push( content.substr( i ), wrap );
- }
-
- this.content = line;
- };
-
- Line.prototype.toString = function()
- {
- return this.content;
- };
+ /** @type {Components.Vim.LineBuffer} */
+ var LineBuffer = ns[ NS_INVOKE ]( "LineBuffer" );
+ /** @type {Components.Vim.Cursor} */
+ var Cursor = ns[ NS_INVOKE ]( "Cursor" );
var Feeder = function( rows, cols )
{
- var lines = [];
+ var lineBuffers = [];
// Last line
- lines[ rows - 1 ] = new Line( cols );
+ lineBuffers[ rows - 1 ] = new LineBuffer( cols );
for( var i = rows - 2; 0 <= i; i -- )
{
- lines[i] = new Line( cols, lines[ i + 1 ] );
+ lineBuffers[i] = new LineBuffer( cols, lineBuffers[ i + 1 ] );
}
- this.lines = lines;
+ this.cursor = new Cursor( lineBuffers );
+
+ this.lineBuffers = lineBuffers;
this.setRender();
};
Feeder.prototype.init = function( content, wrap )
{
if( wrap == undefined ) wrap = true;
- if( this.lines.length )
+ if( this.lineBuffers.length )
{
- this.lines[0].Push( content, wrap );
+ this.lineBuffers[0].Push( content, wrap );
}
};
- // Advance the text to number of lines
- Feeder.prototype.feed = function( num )
- {
- };
-
Feeder.prototype.wrap = function( setwrap )
{
};
@@ -159,30 +86,23 @@
}
}
- Feeder.prototype.cursor = function( direction )
- {
- switch( direction )
- {
- case 0:
- return { start: 0, end: 1 };
- }
- };
-
Feeder.prototype.render = function( start, length )
{
+ var buffs = this.lineBuffers;
+
if( start == undefined ) start = 0;
- else if( this.lines.length < start ) return "";
+ else if( buffs.length < start ) return "";
- if( length == undefined || ( this.lines.length - start ) < length )
- length = this.lines.length - start;
+ if( length == undefined || ( buffs.length - start ) < length )
+ length = buffs.length - start;
if( length == 0 ) return "";
- return this.__render( this.lines[ start ], length - 1 );
+ return this.__render( buffs[ start ], length - 1 );
};
__readOnly( Feeder.prototype, "linesOccupied", function() {
- var line = this.lines[0];
+ var line = this.lineBuffers[0];
if( line.placeholder ) return 0;
var i = 0;
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
index 791f511..159a34f 100644
--- a/botanjs/src/Components/Vim/VimArea.js
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -14,8 +14,9 @@
/** @type {System.Debug} */
var debug = __import( "System.Debug" );
- /** @type {Components.VimArea.LineFeeder} */
+ /** @type {Components.Vim.LineFeeder} */
var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
+ /** @type {Components.Vim.StatusBar} */
var StatusBar = ns[ NS_INVOKE ]( "StatusBar" );
var KeyHandler = function( sender, handler )
@@ -32,6 +33,11 @@
var VimControls = function( sender, e )
{
+ if( e.altKey
+ // F2 - F12
+ || ( 112 < e.keyCode && e.keyCode < 124 )
+ ) return;
+
e.preventDefault();
if( e.ctrlKey )
{
@@ -39,28 +45,49 @@
return;
}
- var kCode = e.KeyCode + ( e.shiftKey ? 1000 : 0 );
- switch( e.KeyCode )
+ var kCode = e.keyCode + ( e.shiftKey ? 1000 : 0 );
+
+ var cfeeder = sender.contentFeeder;
+ switch( kCode )
{
- case 65: // a
- case 1065: // A
- break;
+ // Cursor movements
case 72: // h
- case 1072: // H
+ cfeeder.cursor.moveX( -1 );
break;
case 74: // j
- case 1074: // J
+ cfeeder.cursor.moveY( 1 );
break;
case 75: // k
- case 1075: // K
+ cfeeder.cursor.moveY( -1 );
break;
case 76: // l
- case 1076: // L
+ cfeeder.cursor.moveX( 1 );
+ break;
+
+ case 65: // a
+ case 1065: // A
+ break;
+ case 1072: // H, First line buffer
+ break;
+ case 1076: // L, Last line buffer
+ break;
+ case 1052: // $
+ cfeeder.cursor.lineEnd();
break;
case 1053: // %
+ break;
case 1054: // ^
+ cfeeder.cursor.lineStart();
+ break;
+ case 1074: // J, Join lines
+ break;
+ case 1075: // K, manual entry
break;
+ case 112: // F1, help
}
+
+ sender.__blink = false;
+ sender.select( cfeeder.cursor.position );
};
/* stage @param {Dandelion.IDOMElement} */
@@ -94,31 +121,23 @@
VimArea.prototype.startInput = function( mode )
{
-
- };
-
- VimArea.prototype.cursor = function( x, y )
- {
- return this.__cursor();
};
- VimArea.prototype.flashCursor = function()
+ VimArea.prototype.select = function( sel )
{
- var _self = this;
var textarea = this.stage.element;
- Cycle.perma( "VimCursorFlashCycle", function()
+
+ if( sel )
{
- var cursor = _self.cursor();
- if( cursor )
- {
- textarea.selectionStart = cursor.start;
- textarea.selectionEnd = cursor.end;
- }
- }, 600 );
+ textarea.selectionStart = sel.start;
+ textarea.selectionEnd = sel.end;
+ }
};
VimArea.prototype.VisualizeVimFrame = function()
{
+ var _self = this;
+
var element = this.stage.element;
var r = this.rows;
var c = this.cols;
@@ -132,6 +151,7 @@
sfeeder = new LineFeeder( r, c );
sfeeder.setRender( false );
+ // XXX: Placeholder
var statusBar = new StatusBar( c );
statusBar.stamp( -18, function(){
return "1,1-1";
@@ -143,20 +163,24 @@
sfeeder.init( statusBar.statusText );
- element.value = cfeeder.render( 0, r - sfeeder.linesOccupied ) + "\n" + sfeeder.render();
+ element.value =
+ cfeeder.render( 0, r - sfeeder.linesOccupied )
+ + "\n" + sfeeder.render();
this.contentFeeder = cfeeder;
this.statusFeeder = sfeeder;
- var f = true;
- this.__cursor = function()
- {
- if( f = !f )
- return this.contentFeeder.cursor( 0 );
- else return { start: 0, end: 0 };
- }
+ this.__cursor = cfeeder.cursor;
- this.flashCursor();
+ this.__blink = true;
+ Cycle.perma( "VimCursorBlinkCycle" + element.id, function()
+ {
+ _self.select(
+ ( _self.__blink = !_self.__blink )
+ ? _self.__cursor.position
+ : { start: 0, end: 0 }
+ );
+ }, 600 );
};
ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea );
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
index 706cf48..5de456f 100644
--- a/botanjs/src/Components/Vim/_this.js
+++ b/botanjs/src/Components/Vim/_this.js
@@ -14,6 +14,7 @@
var messages = {
"INSERT": "-- INSERT --"
+ , "REPLACE": "-- REPLACE --"
, "MORE": "-- MORE --"
, "WRITE": "\"%1\" %2L, %3C written"
, "CONTINUE": "Press ENTER or type command to continue"