penguin/AstroJS

Javascript framework for my blog

commit d6bbf245c682048aa723a38257b11c647600681f

author斟酌 鵬兄 <tgckpg@gmail.com>
date2016-03-12T19:30:33Z
subjectSome drafts
commit d6bbf245c682048aa723a38257b11c647600681f
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2016-03-12T19:30:33Z

    Some drafts
---
 botanjs/src/Components/Vim/LineFeeder.js | 195 +++++++++++++++++++++++++++++++
 botanjs/src/Components/Vim/StatusBar.js  |  50 ++++++++
 botanjs/src/Components/Vim/VimArea.js    | 163 ++++++++++++++++++++++++++
 botanjs/src/Components/Vim/_this.css     |   4 +
 botanjs/src/Components/Vim/_this.js      |  42 +++++++
 5 files changed, 454 insertions(+)

diff --git a/botanjs/src/Components/Vim/LineFeeder.js b/botanjs/src/Components/Vim/LineFeeder.js
new file mode 100644
index 0000000..ae8af80
--- /dev/null
+++ b/botanjs/src/Components/Vim/LineFeeder.js
@@ -0,0 +1,195 @@
+(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 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;
+	};
+
+	var Feeder = function( rows, cols )
+	{
+		var lines = [];
+
+		// Last line
+		lines[ rows - 1 ] = new Line( cols );
+
+		for( var i = rows - 2; 0 <= i; i -- )
+		{
+			lines[i] = new Line( cols, lines[ i + 1 ] );
+		}
+
+		this.lines = lines;
+		this.setRender();
+	};
+
+	Feeder.prototype.init = function( content, wrap )
+	{
+		if( wrap == undefined ) wrap = true;
+		if( this.lines.length )
+		{
+			this.lines[0].Push( content, wrap ); 
+		}
+	};
+
+	// Advance the text to number of lines
+	Feeder.prototype.feed = function( num )
+	{
+	};
+
+	Feeder.prototype.wrap = function( setwrap )
+	{
+	};
+
+	Feeder.prototype.setRender = function( placeholder )
+	{
+		if( placeholder == undefined ) placeholder = true;
+
+		if( placeholder )
+		{
+			this.__render = function( line, steps )
+			{
+				var display = ( line == undefined ? "" : line ) + "";
+
+				for( var i = 0;
+					line && i < steps && ( line = line.next );
+					i ++ )
+				{
+					display += "\n" + line;
+				}
+
+				return display;
+			};
+		}
+		else
+		{
+			this.__render = function( line, steps )
+			{
+				var display = ( line == undefined ? "" : line ) + "";
+
+				for( var i = 0;
+					line && i < steps && ( line = line.next ) && !line.placeholder;
+					i ++ )
+				{
+					display += "\n" + line;
+				}
+
+				return display;
+			};
+		}
+	}
+
+	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 "";
+
+		if( length == undefined || ( this.lines.length - start ) < length ) 
+			length = this.lines.length - start;
+
+		if( length == 0 ) return "";
+
+		return this.__render( this.lines[ start ], length - 1 );
+	};
+
+	__readOnly( Feeder.prototype, "linesOccupied", function() {
+		var line = this.lines[0];
+		if( line.placeholder ) return 0;
+
+		var i = 0;
+		do i ++;
+		while( ( line = line.next ) && !line.placeholder );
+		return i;
+	} );
+
+	ns[ NS_EXPORT ]( EX_CLASS, "LineFeeder", Feeder );
+})();
diff --git a/botanjs/src/Components/Vim/StatusBar.js b/botanjs/src/Components/Vim/StatusBar.js
new file mode 100644
index 0000000..9aa4535
--- /dev/null
+++ b/botanjs/src/Components/Vim/StatusBar.js
@@ -0,0 +1,50 @@
+(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" );
+
+	/** @type {Components.VimArea.LineFeeder} */
+	var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
+
+	var StatusBar = function( cols )
+	{
+		this.cols = cols;
+		this.statStamp = {};
+	};
+
+	StatusBar.prototype.stamp = function( pos, func )
+	{
+		this.statStamp[ pos ] = func;
+	};
+
+	__readOnly( StatusBar.prototype, "statusText", function()
+	{
+		var display = "";
+		var l = this.cols;
+
+		for( var i = 0; i < l; i ++ )
+		{
+			var avail = l - i;
+			var text = this.statStamp[ i ] || this.statStamp[ - avail ];
+			if( text )
+			{
+				text = text();
+				display += text.substr( 0, avail );
+				i = display.length - 1;
+			}
+			else display += " ";
+		}
+
+		return display;
+	} );
+
+	ns[ NS_EXPORT ]( EX_CLASS, "StatusBar", StatusBar );
+})();
diff --git a/botanjs/src/Components/Vim/VimArea.js b/botanjs/src/Components/Vim/VimArea.js
new file mode 100644
index 0000000..791f511
--- /dev/null
+++ b/botanjs/src/Components/Vim/VimArea.js
@@ -0,0 +1,163 @@
+(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.utils.DataKey} */
+	var DataKey                                 = __import( "System.utils.DataKey" );
+	/** @type {System.Cycle} */
+	var Cycle                                   = __import( "System.Cycle" );
+	/** @type {System.Debug} */
+	var debug                                   = __import( "System.Debug" );
+
+	/** @type {Components.VimArea.LineFeeder} */
+	var LineFeeder = ns[ NS_INVOKE ]( "LineFeeder" );
+	var StatusBar = ns[ NS_INVOKE ]( "StatusBar" );
+
+	var KeyHandler = function( sender, handler )
+	{
+		return function( e )
+		{
+			e = e || window.event;
+			if ( e.keyCode ) code = e.keyCode;
+			else if ( e.which ) code = e.which;
+
+			handler( sender, e );
+		};
+	};
+
+	var VimControls = function( sender, e )
+	{
+		e.preventDefault();
+		if( e.ctrlKey )
+		{
+			VimComboFunc( sender, e );
+			return;
+		}
+
+		var kCode = e.KeyCode + ( e.shiftKey ? 1000 : 0 );
+		switch( e.KeyCode )
+		{
+			case 65: // a
+			case 1065: // A
+				break;
+			case 72: // h
+			case 1072: // H
+				break;
+			case 74: // j
+			case 1074: // J
+				break;
+			case 75: // k
+			case 1075: // K
+				break;
+			case 76: // l
+			case 1076: // L
+				break;
+			case 1053: // %
+			case 1054: // ^
+				break;
+		}
+	};
+
+	/* stage @param {Dandelion.IDOMElement} */
+	var VimArea = function( stage )
+	{
+		if( !stage ) return;
+
+		var element = stage.element;
+
+		if( element.nodeName != "TEXTAREA" )
+		{
+			debug.Error( "Element is not compatible for VimArea" );
+			return;
+		}
+
+		stage.setAttribute( new DataKey( "vimarea", 1 ) );
+
+		this.stage = stage;
+		this.rows = element.rows;
+		this.cols = element.cols;
+
+		this.PosX = 1;
+		this.PosY = 1;
+
+		stage.addEventListener( "KeyDown", KeyHandler( this, VimControls ) );
+
+		// Init
+		this.content = element.value;
+		this.VisualizeVimFrame();
+	};
+
+	VimArea.prototype.startInput = function( mode )
+	{
+		
+	};
+
+	VimArea.prototype.cursor = function( x, y )
+	{
+		return this.__cursor();
+	};
+
+	VimArea.prototype.flashCursor = function()
+	{
+		var _self = this;
+		var textarea = this.stage.element;
+		Cycle.perma( "VimCursorFlashCycle", function()
+		{
+			var cursor = _self.cursor();
+			if( cursor )
+			{
+				textarea.selectionStart = cursor.start;
+				textarea.selectionEnd = cursor.end;
+			}
+		}, 600 );
+	};
+
+	VimArea.prototype.VisualizeVimFrame = function()
+	{
+		var element = this.stage.element;
+		var r = this.rows;
+		var c = this.cols;
+
+		// Content feeder
+		var cfeeder = new LineFeeder( r, c );
+
+		cfeeder.init( this.content );
+
+		// Status feeder
+		sfeeder = new LineFeeder( r, c );
+		sfeeder.setRender( false );
+
+		var statusBar = new StatusBar( c );
+		statusBar.stamp( -18, function(){
+			return "1,1-1";
+		});
+
+		statusBar.stamp( -3, function(){
+			return "All";
+		});
+
+		sfeeder.init( statusBar.statusText );
+
+		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.flashCursor();
+	};
+
+	ns[ NS_EXPORT ]( EX_CLASS, "VimArea", VimArea );
+})();
diff --git a/botanjs/src/Components/Vim/_this.css b/botanjs/src/Components/Vim/_this.css
new file mode 100644
index 0000000..1716ca4
--- /dev/null
+++ b/botanjs/src/Components/Vim/_this.css
@@ -0,0 +1,4 @@
+textarea[data-vimarea="1"] {
+	color: transparent;
+	text-shadow: 0 0 0 #000;
+}
diff --git a/botanjs/src/Components/Vim/_this.js b/botanjs/src/Components/Vim/_this.js
new file mode 100644
index 0000000..706cf48
--- /dev/null
+++ b/botanjs/src/Components/Vim/_this.js
@@ -0,0 +1,42 @@
+(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 messages = {
+		"INSERT": "-- INSERT --"
+		, "MORE": "-- MORE --"
+		, "WRITE": "\"%1\" %2L, %3C written"
+		, "CONTINUE": "Press ENTER or type command to continue"
+		, "SEARCH_HIT_BOTTOM": "Seach hit BOTTOM, contining at TOP"
+		, "TOP": "Top"
+		, "BOTTOM": "Bot"
+		, "ALL": "All"
+		, "EXIT": "Type :quit<Enter>  to exit Vim"
+	};
+
+	var errors = {
+		"E486": "E486: Pattern not found: %1"
+	};
+
+	var Message = function( key )
+	{
+		var restArgs = Array.prototype.slice.apply( arguments, 1 );
+		var i = 0;
+		return messages[ key ].replace( /%\d+/g, function( e )
+		{
+			return restArgs[ i ++ ];
+		} );
+	};
+
+	ns[ NS_EXPORT ]( EX_FUNC, "Message", Message );
+})();