forked from Botanical/BotanJS
Merge remote-tracking branches 'vim/master' and 'origin/master' into Astro
This commit is contained in:
commit
9e0af1531f
@ -40,6 +40,9 @@
|
||||
|
||||
var cur = this.__cursor;
|
||||
var Vim = cur.Vim;
|
||||
|
||||
/** @type {Components.Vim.VimArea} */
|
||||
var VimArea = shadowImport( "Components.Vim.VimArea" );
|
||||
var Insts = VimArea.Instances;
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
}
|
||||
|
||||
// The root bracket as back ref 0
|
||||
var RegEx = new RegExp( "(" + parsed + ")", "g" );
|
||||
var RegEx = new RegExp( "(" + parsed + ")", "gm" );
|
||||
|
||||
return RegEx;
|
||||
};
|
||||
@ -104,9 +104,20 @@
|
||||
var FirstHit;
|
||||
var PrevStack = [];
|
||||
|
||||
var LoopGuard;
|
||||
while( ( r = search.exec( content ) ) !== null )
|
||||
{
|
||||
if( !FirstHit ) FirstHit = r.index;
|
||||
if( FirstHit == undefined )
|
||||
{
|
||||
FirstHit = r.index;
|
||||
}
|
||||
|
||||
if( LoopGuard == r.index )
|
||||
{
|
||||
this.__msg = VimError( "EX2", PATTERN.slice( 1 ).join( "" ) );
|
||||
return true;
|
||||
}
|
||||
|
||||
if( p < r.index )
|
||||
{
|
||||
Hit = r.index;
|
||||
@ -114,6 +125,7 @@
|
||||
}
|
||||
|
||||
PrevStack.push( r.index );
|
||||
LoopGuard = r.index;
|
||||
}
|
||||
|
||||
if( e.kMap( "N" ) )
|
||||
|
89
botanjs/src/Components/Vim/Actions/JOIN_LINES.js
Normal file
89
botanjs/src/Components/Vim/Actions/JOIN_LINES.js
Normal file
@ -0,0 +1,89 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.Actions" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
/** @type {Components.Vim.State.Stator} */
|
||||
var Stator = __import( "Components.Vim.State.Stator" );
|
||||
/** @type {Components.Vim.State.Stack} */
|
||||
var Stack = __import( "Components.Vim.State.Stack" );
|
||||
|
||||
var beep = __import( "Components.Vim.Beep" );
|
||||
var Mesg = __import( "Components.Vim.Message" );
|
||||
|
||||
var occurance = __import( "System.utils.Perf.CountSubstr" );
|
||||
|
||||
/** @type {Components.Vim.IAction} */
|
||||
var JOIN_LINES = function( Cursor )
|
||||
{
|
||||
/** @type {Components.Vim.Cursor} */
|
||||
this.__cursor = Cursor;
|
||||
this.__msg = "";
|
||||
Cursor.suppressEvent();
|
||||
};
|
||||
|
||||
JOIN_LINES.prototype.dispose = function()
|
||||
{
|
||||
this.__cursor.unsuppressEvent();
|
||||
};
|
||||
|
||||
JOIN_LINES.prototype.handler = function( e, range )
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var cur = this.__cursor;
|
||||
var feeder = cur.feeder;
|
||||
|
||||
var start;
|
||||
var end;
|
||||
|
||||
var stack;
|
||||
var stator;
|
||||
|
||||
var contentUndo;
|
||||
if( range )
|
||||
{
|
||||
start = range.start;
|
||||
end = range.close;
|
||||
}
|
||||
else
|
||||
{
|
||||
var oPos = cur.aPos;
|
||||
cur.lineEnd( true );
|
||||
stator = new Stator( cur );
|
||||
start = cur.aPos;
|
||||
cur.moveY( 1 );
|
||||
cur.lineStart();
|
||||
end = cur.aPos;
|
||||
|
||||
// This happens on the last line
|
||||
if( end < start )
|
||||
{
|
||||
cur.moveTo( oPos );
|
||||
beep();
|
||||
return true;
|
||||
}
|
||||
|
||||
var content = feeder.content;
|
||||
|
||||
contentUndo = feeder.content.substring( start, end );
|
||||
feeder.content = content.substring( 0, start ) + " " + content.substr( end );
|
||||
}
|
||||
|
||||
feeder.pan();
|
||||
|
||||
cur.moveTo( start );
|
||||
|
||||
var stack = new Stack();
|
||||
stack.store( stator.save( 1, contentUndo ) );
|
||||
|
||||
cur.rec.record( stack );
|
||||
};
|
||||
|
||||
JOIN_LINES.prototype.getMessage = function()
|
||||
{
|
||||
return this.__msg;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "JOIN_LINES", JOIN_LINES );
|
||||
})();
|
82
botanjs/src/Components/Vim/Actions/TO.js
Normal file
82
botanjs/src/Components/Vim/Actions/TO.js
Normal file
@ -0,0 +1,82 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.Actions" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
var beep = __import( "Components.Vim.Beep" );
|
||||
|
||||
/** @type {Components.Vim.IAction} */
|
||||
var TO = function( Cursor )
|
||||
{
|
||||
/** @type {Components.Vim.Cursor} */
|
||||
this.__cursor = Cursor;
|
||||
this.__msg = "<TO COMMAND>";
|
||||
Cursor.suppressEvent();
|
||||
};
|
||||
|
||||
TO.prototype.dispose = function()
|
||||
{
|
||||
this.__cursor.unsuppressEvent();
|
||||
};
|
||||
|
||||
TO.prototype.handler = function( em, et )
|
||||
{
|
||||
et.preventDefault();
|
||||
|
||||
var cur = this.__cursor;
|
||||
var f = cur.feeder;
|
||||
var n = cur.getLine().lineNum;
|
||||
|
||||
var p = 0;
|
||||
for( i = 0; p != -1 && i < n; i ++ )
|
||||
{
|
||||
p = f.content.indexOf( "\n", p + 1 );
|
||||
}
|
||||
|
||||
var upperLimit = f.content.indexOf( "\n", p + 1 );
|
||||
|
||||
if( 0 < n ) p ++;
|
||||
|
||||
var lowerLimmit = p;
|
||||
|
||||
var cX = cur.X;
|
||||
var tX = cX;
|
||||
|
||||
var Char = et.key;
|
||||
if( et.kMap( "Tab" ) )
|
||||
{
|
||||
Char = "\t";
|
||||
}
|
||||
|
||||
if( 1 < Char.length )
|
||||
{
|
||||
beep();
|
||||
return;
|
||||
}
|
||||
|
||||
// Forward
|
||||
if( em.kMap( "t" ) || em.kMap( "f" ) )
|
||||
{
|
||||
tX = f.content.indexOf( Char, p + cX + 1 );
|
||||
}
|
||||
// backward
|
||||
else
|
||||
{
|
||||
tX = f.content.lastIndexOf( Char, p + cX - 1 );
|
||||
}
|
||||
|
||||
if( lowerLimmit <= tX && tX < upperLimit )
|
||||
{
|
||||
cur.moveTo( tX );
|
||||
}
|
||||
else beep();
|
||||
};
|
||||
|
||||
TO.prototype.getMessage = function()
|
||||
{
|
||||
return this.__msg;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "TO", TO );
|
||||
})();
|
74
botanjs/src/Components/Vim/Actions/WORD.js
Normal file
74
botanjs/src/Components/Vim/Actions/WORD.js
Normal file
@ -0,0 +1,74 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.Actions" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
/** @type {Components.Vim.IAction} */
|
||||
var WORD = function( Cursor )
|
||||
{
|
||||
/** @type {Components.Vim.Cursor} */
|
||||
this.__cursor = Cursor;
|
||||
this.__msg = "<WORD COMMAND>";
|
||||
Cursor.suppressEvent();
|
||||
};
|
||||
|
||||
WORD.prototype.dispose = function()
|
||||
{
|
||||
this.__cursor.unsuppressEvent();
|
||||
};
|
||||
|
||||
WORD.prototype.handler = function( e )
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
var cur = this.__cursor;
|
||||
var feeder = cur.feeder;
|
||||
|
||||
var analyzer = cur.Vim.contentAnalyzer;
|
||||
var p = cur.aPos;
|
||||
|
||||
|
||||
var d = 1;
|
||||
// forward
|
||||
if( e.kMap( "w" ) || e.kMap( "W" ) )
|
||||
{
|
||||
if( feeder.content[ p + 1 ] == "\n" )
|
||||
{
|
||||
p ++;
|
||||
}
|
||||
|
||||
var wordRange = analyzer.wordAt( p );
|
||||
if( wordRange.open != -1 )
|
||||
{
|
||||
p = wordRange.close + 1;
|
||||
}
|
||||
}
|
||||
// Backward
|
||||
if( e.kMap( "b" ) || e.kMap( "B" ) )
|
||||
{
|
||||
if( p == 0 ) return;
|
||||
d = -1;
|
||||
|
||||
var wordRange = analyzer.wordAt( p - 1 );
|
||||
if( wordRange.open != -1 )
|
||||
{
|
||||
p = wordRange.open;
|
||||
}
|
||||
}
|
||||
|
||||
while( " \t".indexOf( feeder.content[ p ] ) != -1 )
|
||||
{
|
||||
p += d;
|
||||
}
|
||||
|
||||
cur.moveTo( p );
|
||||
};
|
||||
|
||||
WORD.prototype.getMessage = function()
|
||||
{
|
||||
return this.__msg;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "WORD", WORD );
|
||||
})();
|
@ -47,6 +47,8 @@
|
||||
var COMMA = 188; var FULLSTOP = 190;
|
||||
var SLASH = 191; var BACK_SLASH = 220;
|
||||
|
||||
var ANY_KEY = -1;
|
||||
|
||||
var __maps = {};
|
||||
var Map = function( str )
|
||||
{
|
||||
@ -169,8 +171,9 @@
|
||||
{
|
||||
var compReg = this.__compositeReg[i];
|
||||
var keys = compReg.keys;
|
||||
var key = keys[ compReg.i ++ ];
|
||||
|
||||
if( keys[ compReg.i ++ ] == kCode )
|
||||
if( key == ANY_KEY || key == kCode )
|
||||
{
|
||||
if( compReg.i == keys.length )
|
||||
{
|
||||
@ -262,6 +265,7 @@
|
||||
case SHIFT + I: // Append before the line start, after spaces
|
||||
break;
|
||||
case SHIFT + J: // Join lines
|
||||
ccur.openRunAction( "JOIN_LINES", e );
|
||||
break;
|
||||
case SHIFT + K: // Find the manual entry
|
||||
break;
|
||||
@ -374,7 +378,11 @@
|
||||
break;
|
||||
case SHIFT + L: // Last line buffer
|
||||
break;
|
||||
case SHIFT + _6: // ^, Start
|
||||
|
||||
case _0: // Really - line Start
|
||||
ccur.lineStart();
|
||||
break;
|
||||
case SHIFT + _6: // ^, line Start, XXX: skip tabs
|
||||
ccur.lineStart();
|
||||
break;
|
||||
case SHIFT + _4: // $, End
|
||||
@ -404,8 +412,45 @@
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case SHIFT + T: // To
|
||||
case T: // To
|
||||
this.__cMovement = true;
|
||||
|
||||
this.__composite( e, function( e2 ) {
|
||||
var oX = ccur.X;
|
||||
ccur.openRunAction( "TO", e, e2 );
|
||||
|
||||
if( ccur.X < oX )
|
||||
{
|
||||
ccur.moveX( 1 );
|
||||
}
|
||||
else if( oX < ccur.X )
|
||||
{
|
||||
ccur.moveX( -1 );
|
||||
}
|
||||
}, ANY_KEY );
|
||||
|
||||
break;
|
||||
case SHIFT + F: // To
|
||||
case F: // To
|
||||
this.__cMovement = true;
|
||||
|
||||
this.__composite( e, function( e2 ) {
|
||||
ccur.openRunAction( "TO", e, e2 );
|
||||
}, ANY_KEY );
|
||||
|
||||
break;
|
||||
|
||||
case W: // word
|
||||
case SHIFT + W:
|
||||
case B:
|
||||
case SHIFT + B:
|
||||
ccur.openRunAction( "WORD", e );
|
||||
break
|
||||
|
||||
|
||||
case I: // In between boundary
|
||||
if( !ccur.action )
|
||||
{
|
||||
|
@ -137,7 +137,6 @@
|
||||
|
||||
this.moveX( - Number.MAX_VALUE );
|
||||
this.moveX( jumpX, false, phantomSpace );
|
||||
|
||||
};
|
||||
|
||||
// 0 will be treated as default ( 1 )
|
||||
|
@ -199,6 +199,10 @@
|
||||
// C1 Controls and Latin-1 Supplement (Extended ASCII)
|
||||
[ 0x00A1, 0x00AC ], [ 0x00AE, 0x00BF ]
|
||||
]
|
||||
,
|
||||
[ // Spaces & tabs
|
||||
[ 0x0020, 0x0020 ], [ 0x0009, 0x0009 ]
|
||||
]
|
||||
];
|
||||
|
||||
var NUM_KINGDOM = KINGDOMS.length;
|
||||
|
@ -42,16 +42,27 @@
|
||||
};
|
||||
|
||||
/* stage @param {Dandelion.IDOMElement} */
|
||||
var VimArea = function( stage )
|
||||
var VimArea = function( stage, detectScreenSize )
|
||||
{
|
||||
if( !stage ) return;
|
||||
if( !stage ) throw new Error( "Invalid argument" );
|
||||
|
||||
stage = IDOMElement( stage );
|
||||
|
||||
var element = stage.element;
|
||||
|
||||
if( element.nodeName != "TEXTAREA" )
|
||||
if(!( element && element.nodeName == "TEXTAREA" ))
|
||||
{
|
||||
debug.Error( "Element is not compatible for VimArea" );
|
||||
return;
|
||||
throw new Error( "This element is not compatible for VimArea" );
|
||||
}
|
||||
|
||||
for( var i in Insts )
|
||||
{
|
||||
var inst = Insts[ i ];
|
||||
if( inst.stage.element == element )
|
||||
{
|
||||
debug.Info( "Instance exists" );
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
|
||||
stage.setAttribute( new DataKey( "vimarea", 1 ) );
|
||||
@ -69,10 +80,16 @@
|
||||
, new EventKey( "Blur", function() { _self.__active = false; } )
|
||||
];
|
||||
|
||||
this.__removeText
|
||||
|
||||
// Init
|
||||
this.VisualizeVimFrame( element.value );
|
||||
if( detectScreenSize )
|
||||
{
|
||||
var val = element.value;
|
||||
this.__testScreen(function() { _self.VisualizeVimFrame( val ); });
|
||||
}
|
||||
else
|
||||
{
|
||||
this.VisualizeVimFrame( element.value );
|
||||
}
|
||||
|
||||
// Set buffer index
|
||||
this.__instIndex = InstIndex ++;
|
||||
@ -81,6 +98,68 @@
|
||||
Insts[ this.__instIndex ] = this;
|
||||
};
|
||||
|
||||
VimArea.prototype.__testScreen = function( handler )
|
||||
{
|
||||
var area = this.stage.element;
|
||||
area.value = "";
|
||||
|
||||
var msg = "Please wait while Vim;Re is testing for screen dimensions";
|
||||
var m = function() { return msg[ i ++ ] || "."; };
|
||||
|
||||
var i = 0;
|
||||
|
||||
var oX = area.style.overflowX;
|
||||
var oY = area.style.overflowY;
|
||||
|
||||
area.style.whiteSpace = "nowrap";
|
||||
|
||||
var oWidth = area.scrollWidth;
|
||||
var testWidth = function()
|
||||
{
|
||||
area.value += m();
|
||||
if( oWidth == area.scrollWidth )
|
||||
{
|
||||
Cycle.next( testWidth );
|
||||
}
|
||||
else
|
||||
{
|
||||
var t = "";
|
||||
i -= 3;
|
||||
for( var k = 0; k < i; k ++ ) t += ".";
|
||||
area.value = t;
|
||||
|
||||
area.style.whiteSpace = "";
|
||||
m = function() { return "\n" + t; };
|
||||
testHeight();
|
||||
}
|
||||
};
|
||||
|
||||
testWidth();
|
||||
|
||||
var oHeight = area.scrollHeight;
|
||||
|
||||
var l = 0;
|
||||
|
||||
var _self = this;
|
||||
|
||||
var testHeight = function() {
|
||||
area.value += m();
|
||||
l ++;
|
||||
|
||||
if( oHeight == area.scrollHeight )
|
||||
{
|
||||
Cycle.next( testHeight );
|
||||
}
|
||||
else
|
||||
{
|
||||
_self.rows = l;
|
||||
_self.cols = i;
|
||||
|
||||
handler();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
VimArea.prototype.select = function( sel )
|
||||
{
|
||||
if( !this.__active ) return;
|
||||
|
@ -38,6 +38,7 @@ VIMRE_VERSION = "1.0.0b";
|
||||
|
||||
// EXtended Errors
|
||||
, "EX1": "Pattern Error( %1 )"
|
||||
, "EX2": "This pattern is causing infinite loop: %1"
|
||||
|
||||
, "TODO": "%1 is not implemented yet"
|
||||
, "MISSING_FEATURE": "Sorry, I thought this command wasn't useful enough to implement. Please file a feature request titled \"Implement %1\" in github if you think this is important."
|
||||
|
@ -10,6 +10,12 @@
|
||||
|
||||
var tList = [];
|
||||
|
||||
var C_CALLBACK = 0;
|
||||
var C_TIME = 1;
|
||||
var C_ONCE = 2;
|
||||
var C_ID = 3;
|
||||
var C_INTVL = 4;
|
||||
|
||||
var stepper = function()
|
||||
{
|
||||
var thisTime = new Date().getTime();
|
||||
@ -21,11 +27,11 @@
|
||||
for ( var i in tList )
|
||||
{
|
||||
var f = tList[i];
|
||||
if( f && thisTime > f[1] )
|
||||
if( f && thisTime > f[ C_TIME ] )
|
||||
{
|
||||
try
|
||||
{
|
||||
f[0]();
|
||||
f[ C_CALLBACK ]();
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
@ -34,13 +40,13 @@
|
||||
continue;
|
||||
}
|
||||
|
||||
if( f[2] )
|
||||
if( f[ C_ONCE ] )
|
||||
{
|
||||
delete tList[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
f[1] = thisTime + f[4];
|
||||
f[ C_TIME ] = thisTime + f[ C_INTVL ];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -56,7 +62,7 @@
|
||||
{
|
||||
for ( var i in tList )
|
||||
{
|
||||
if( tList[i][3] == id )
|
||||
if( tList[i][ C_ID ] == id )
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -68,14 +74,19 @@
|
||||
// 3: id
|
||||
for ( var i in tList )
|
||||
{
|
||||
if( tList[i][3] == id )
|
||||
if( tList[i][ C_ID ] == id )
|
||||
delete tList[i];
|
||||
}
|
||||
};
|
||||
|
||||
var next = function( func )
|
||||
{
|
||||
tList[ tList.length ] = [ func, 0, true ];
|
||||
var a = [];
|
||||
a[ C_CALLBACK ] = func;
|
||||
a[ C_TIME ] = 0;
|
||||
a[ C_ONCE ] = true;
|
||||
|
||||
tList[ tList.length ] = a;
|
||||
};
|
||||
|
||||
var ourTick = new Tick();
|
||||
|
Loading…
Reference in New Issue
Block a user