forked from Botanical/BotanJS
Some navigation, but not working:(
This commit is contained in:
parent
6ce714be1e
commit
751530b42d
162
botanjs/src/Components/Vim/Cursor.js
Normal file
162
botanjs/src/Components/Vim/Cursor.js
Normal file
@ -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 );
|
||||
})();
|
111
botanjs/src/Components/Vim/LineBuffer.js
Normal file
111
botanjs/src/Components/Vim/LineBuffer.js
Normal file
@ -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 );
|
||||
})();
|
@ -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 )
|
||||
{
|
||||
if( start == undefined ) start = 0;
|
||||
else if( this.lines.length < start ) return "";
|
||||
var buffs = this.lineBuffers;
|
||||
|
||||
if( length == undefined || ( this.lines.length - start ) < length )
|
||||
length = this.lines.length - start;
|
||||
if( start == undefined ) start = 0;
|
||||
else if( buffs.length < start ) return "";
|
||||
|
||||
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;
|
||||
|
@ -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 )
|
||||
{
|
||||
// Cursor movements
|
||||
case 72: // h
|
||||
cfeeder.cursor.moveX( -1 );
|
||||
break;
|
||||
case 74: // j
|
||||
cfeeder.cursor.moveY( 1 );
|
||||
break;
|
||||
case 75: // k
|
||||
cfeeder.cursor.moveY( -1 );
|
||||
break;
|
||||
case 76: // l
|
||||
cfeeder.cursor.moveX( 1 );
|
||||
break;
|
||||
|
||||
case 65: // a
|
||||
case 1065: // A
|
||||
break;
|
||||
case 72: // h
|
||||
case 1072: // H
|
||||
case 1072: // H, First line buffer
|
||||
break;
|
||||
case 74: // j
|
||||
case 1074: // J
|
||||
case 1076: // L, Last line buffer
|
||||
break;
|
||||
case 75: // k
|
||||
case 1075: // K
|
||||
break;
|
||||
case 76: // l
|
||||
case 1076: // L
|
||||
case 1052: // $
|
||||
cfeeder.cursor.lineEnd();
|
||||
break;
|
||||
case 1053: // %
|
||||
case 1054: // ^
|
||||
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 )
|
||||
VimArea.prototype.select = function( sel )
|
||||
{
|
||||
return this.__cursor();
|
||||
};
|
||||
|
||||
VimArea.prototype.flashCursor = function()
|
||||
{
|
||||
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 );
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user