forked from Botanical/BotanJS
Added :{number} support
This commit is contained in:
parent
68ee6dacc6
commit
1511c70957
@ -79,6 +79,9 @@
|
||||
case "registers":
|
||||
out[ CMD_TYPE ] = "REGISTERS";
|
||||
break;
|
||||
case "marks":
|
||||
out[ CMD_TYPE ] = "MARKS";
|
||||
break;
|
||||
case "ver":
|
||||
case "version":
|
||||
out[ CMD_TYPE ] = "VERSION";
|
||||
@ -90,6 +93,13 @@
|
||||
case "varec":
|
||||
out[ CMD_TYPE ] = "VA_REC";
|
||||
break;
|
||||
|
||||
case "": // Range jumping
|
||||
pattern.push( true );
|
||||
case "p":
|
||||
allowRange = true;
|
||||
out[ CMD_TYPE ] = "PRINT";
|
||||
break;
|
||||
}
|
||||
|
||||
if( range !== "" )
|
||||
|
83
botanjs/src/Components/Vim/Actions/MARKS.js
Normal file
83
botanjs/src/Components/Vim/Actions/MARKS.js
Normal file
@ -0,0 +1,83 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.Actions" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
var VimError = __import( "Components.Vim.Error" );
|
||||
var Mesg = __import( "Components.Vim.Message" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var Marks = __import( "Components.Vim.State.Marks" );
|
||||
var Keys = Marks.Keys;
|
||||
|
||||
/** @type {Components.Vim.IAction} */
|
||||
var MARKS = function( Cursor )
|
||||
{
|
||||
/** @type {Components.Vim.Cursor} */
|
||||
this.__cursor = Cursor;
|
||||
this.__msg = "";
|
||||
Cursor.suppressEvent();
|
||||
};
|
||||
|
||||
MARKS.prototype.dispose = function()
|
||||
{
|
||||
this.__cursor.unsuppressEvent();
|
||||
};
|
||||
|
||||
MARKS.prototype.handler = function( e, p )
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
/** @type {Components.Vim.State.Marks} */
|
||||
var marks = e.target.marks;
|
||||
|
||||
var msg = ":marks";
|
||||
|
||||
/**
|
||||
* Regarding to marks 0-9, from Vim docs
|
||||
* Numbered marks '0 to '9 are quite different. They can not be set directly.
|
||||
* They are only present when using a viminfo file viminfo-file. Basically '0
|
||||
* is the location of the cursor when you last exited Vim, '1 the last but one
|
||||
* time, etc. Use the "r" flag in 'viminfo' to specify files for which no
|
||||
* Numbered mark should be stored. See viminfo-file-marks.
|
||||
* TODO: Need to redefine marks 0-9
|
||||
**/
|
||||
|
||||
// Fuck this, use silly paddings
|
||||
msg += "\nmark line col file/text";
|
||||
|
||||
var feeder = this.__cursor.feeder;
|
||||
for( var i = 0, j = Keys[ i ]; j != undefined; i ++, j = Keys[ i ] )
|
||||
{
|
||||
var r = marks.get( j );
|
||||
if( !r ) continue;
|
||||
|
||||
var line = ( r[0] + 1 ) + "";
|
||||
var col = ( r[1] + 1 ) + "";
|
||||
var t = feeder.line( r[0] - 1 ).replace( /^[\t ]+/, "" );
|
||||
|
||||
var ll = 4 - line.length;
|
||||
for( var il = 0; il < ll; il ++ ) line = " " + line;
|
||||
|
||||
var ll = 3 - col.length;
|
||||
for( var il = 0; il < ll; il ++ ) col = " " + col;
|
||||
|
||||
msg += "\n " + j + " " + line + " " + col + " " + t;
|
||||
}
|
||||
|
||||
var lastLine = Mesg( "WAIT_FOR_INPUT" );
|
||||
|
||||
var l = this.__cursor.feeder.firstBuffer.cols;
|
||||
for( var i = msg.length; i < l; i ++ ) msg += " ";
|
||||
|
||||
this.__msg = msg + "\n" + lastLine;
|
||||
};
|
||||
|
||||
MARKS.prototype.getMessage = function()
|
||||
{
|
||||
return this.__msg;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "MARKS", MARKS );
|
||||
})();
|
48
botanjs/src/Components/Vim/Actions/PRINT.js
Normal file
48
botanjs/src/Components/Vim/Actions/PRINT.js
Normal file
@ -0,0 +1,48 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.Actions" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
/** @type {Components.Vim.IAction} */
|
||||
var PRINT = function( Cursor )
|
||||
{
|
||||
/** @type {Components.Vim.Cursor} */
|
||||
this.__cursor = Cursor;
|
||||
this.__msg = "";
|
||||
};
|
||||
|
||||
PRINT.prototype.dispose = function() { };
|
||||
PRINT.prototype.handler = function( e, args, range )
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
if( args[0] === true )
|
||||
{
|
||||
switch( range )
|
||||
{
|
||||
case "%":
|
||||
case "$":
|
||||
this.__cursor.moveY( Number.MAX_VALUE );
|
||||
return;
|
||||
case ".":
|
||||
this.__cursor.lineStart( true );
|
||||
break;
|
||||
case "":
|
||||
default:
|
||||
var lineNum = parseInt( range ) - 1;
|
||||
if( lineNum )
|
||||
{
|
||||
this.__cursor.gotoLine( 0 < lineNum ? lineNum : 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PRINT.prototype.getMessage = function()
|
||||
{
|
||||
return this.__msg;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "PRINT", PRINT );
|
||||
})();
|
@ -478,16 +478,17 @@
|
||||
{
|
||||
var kCode = e.keyCode;
|
||||
|
||||
if( this.__cMovement )
|
||||
if( this.__captureComp )
|
||||
{
|
||||
if( !e.ModKeys )
|
||||
{
|
||||
this.__composite( e );
|
||||
this.__cMovement = false;
|
||||
this.__captureComp = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var inst = this.__vimArea;
|
||||
var ccur = this.__ccur;
|
||||
var cfeeder = ccur.feeder;
|
||||
|
||||
@ -610,10 +611,22 @@
|
||||
|
||||
break;
|
||||
|
||||
case M:
|
||||
this.__captureComp = true;
|
||||
|
||||
var marks = this.__vimArea.marks;
|
||||
this.__composite( e, function( e2 ) {
|
||||
var line = ccur.getLine().lineNum;
|
||||
if( !marks.set( e2.key, line, ccur.aX ) )
|
||||
{
|
||||
beep();
|
||||
}
|
||||
}, ANY_KEY );
|
||||
break;
|
||||
|
||||
case SHIFT + T: // To
|
||||
case T: // To
|
||||
this.__cMovement = true;
|
||||
this.__captureComp = true;
|
||||
|
||||
this.__composite( e, function( e2 ) {
|
||||
var oX = ccur.X;
|
||||
@ -632,7 +645,7 @@
|
||||
break;
|
||||
case SHIFT + F: // To
|
||||
case F: // To
|
||||
this.__cMovement = true;
|
||||
this.__captureComp = true;
|
||||
|
||||
this.__composite( e, function( e2 ) {
|
||||
ccur.openRunAction( "TO", e, e2 );
|
||||
@ -659,7 +672,7 @@
|
||||
|
||||
var analyzer = this.__vimArea.contentAnalyzer;
|
||||
|
||||
this.__cMovement = true;
|
||||
this.__captureComp = true;
|
||||
|
||||
// Word boundary
|
||||
this.__composite( e, function( e2 ) {
|
||||
@ -703,7 +716,7 @@
|
||||
|
||||
case G:
|
||||
|
||||
this.__cMovement = true;
|
||||
this.__captureComp = true;
|
||||
|
||||
// Go to top
|
||||
this.__composite( e, function() {
|
||||
@ -775,7 +788,7 @@
|
||||
break;
|
||||
|
||||
case SLASH: // "/" Search movement
|
||||
this.__cMovement = true;
|
||||
this.__captureComp = true;
|
||||
|
||||
this.__divedCCmd = new ExCommand( ccur, "/" );
|
||||
this.__divedCCmd.handler( e );
|
||||
@ -788,7 +801,7 @@
|
||||
break;
|
||||
}
|
||||
|
||||
this.__cMovement = true;
|
||||
this.__captureComp = true;
|
||||
|
||||
var exCmd = new ExCommand( ccur, ":" );
|
||||
exCmd.handler( e );
|
||||
@ -827,7 +840,7 @@
|
||||
if( e.Escape )
|
||||
{
|
||||
var b = false;
|
||||
this.__cMovement = false;
|
||||
this.__captureComp = false;
|
||||
|
||||
if( this.__compositeReg )
|
||||
{
|
||||
@ -853,7 +866,7 @@
|
||||
if( this.__divedCCmd.handler( e ) )
|
||||
{
|
||||
this.__divedCCmd.dispose();
|
||||
this.__cMovement = false;
|
||||
this.__captureComp = false;
|
||||
this.__divedCCmd = null;
|
||||
return;
|
||||
}
|
||||
@ -864,7 +877,7 @@
|
||||
var cfeeder = this.__cfeeder;
|
||||
var ccur = this.__ccur;
|
||||
|
||||
if( !this.__cMovement && ( !ccur.action || ccur.action.allowMovement ) )
|
||||
if( !this.__captureComp && ( !ccur.action || ccur.action.allowMovement ) )
|
||||
{
|
||||
this.__modCommand( e );
|
||||
if( e.canceled ) return;
|
||||
|
@ -106,6 +106,8 @@
|
||||
// Move to an absolute position
|
||||
Cursor.prototype.moveTo = function( aPos, phantomSpace, skipTabs )
|
||||
{
|
||||
this.__suppressUpdate();
|
||||
|
||||
var content = this.feeder.content;
|
||||
var pline = this.getLine();
|
||||
var lastLineNum = pline.lineNum;
|
||||
@ -131,10 +133,7 @@
|
||||
}
|
||||
|
||||
var jumpY = expLineNum - lastLineNum;
|
||||
if( jumpY )
|
||||
{
|
||||
this.moveY( jumpY );
|
||||
}
|
||||
if( jumpY ) this.moveY( jumpY );
|
||||
|
||||
pline = this.getLine();
|
||||
|
||||
@ -163,6 +162,50 @@
|
||||
|
||||
this.moveX( - Number.MAX_VALUE, false, false, true );
|
||||
this.moveX( jumpX, false, phantomSpace, skipTabs );
|
||||
|
||||
this.__unsuppressUpdate();
|
||||
};
|
||||
|
||||
// A line-only variant of moveTo, de-generalized for the sake of performance
|
||||
Cursor.prototype.gotoLine = function( n )
|
||||
{
|
||||
this.__suppressUpdate();
|
||||
|
||||
var content = this.feeder.content;
|
||||
var pline = this.getLine();
|
||||
var lastLineNum = pline.lineNum;
|
||||
|
||||
if( pline.placeholder )
|
||||
{
|
||||
lastLineNum = 0;
|
||||
this.Y = 0;
|
||||
}
|
||||
|
||||
var expLineNum = 0;
|
||||
var lineStart = 0;
|
||||
for( var i = content.indexOf( "\n" ); 0 <= i ; i = content.indexOf( "\n", i ) )
|
||||
{
|
||||
if( expLineNum == n ) break;
|
||||
lineStart = i;
|
||||
i ++;
|
||||
expLineNum ++;
|
||||
}
|
||||
|
||||
if( expLineNum < n ) n = expLineNum;
|
||||
|
||||
var jumpY = expLineNum - lastLineNum;
|
||||
if( jumpY ) this.moveY( jumpY );
|
||||
|
||||
pline = this.getLine();
|
||||
|
||||
if( pline.lineNum != expLineNum )
|
||||
{
|
||||
this.moveY( expLineNum - pline.lineNum );
|
||||
}
|
||||
|
||||
this.lineStart( true );
|
||||
|
||||
this.__unsuppressUpdate();
|
||||
};
|
||||
|
||||
// 0 will be treated as default ( 1 )
|
||||
@ -323,7 +366,7 @@
|
||||
else if( c == "\n" )
|
||||
{
|
||||
x += d;
|
||||
}
|
||||
}
|
||||
|
||||
// Wordwrap phantomSpace movement compensation on max filled lines
|
||||
if( feeder.wrap && boundary && !hasPhantomSpace && phantomSpace )
|
||||
@ -369,10 +412,12 @@
|
||||
this.moveX( Number.MAX_VALUE, false, phantomSpace, true );
|
||||
};
|
||||
|
||||
// Because LineOffset is costly, suppress unnecessary calls
|
||||
Cursor.prototype.updatePosition = function()
|
||||
{
|
||||
var feeder = this.feeder;
|
||||
var P = this.X + LineOffset( feeder.lineBuffers, this.Y ) + this.__off;
|
||||
if( 0 < this.__suppUpdate ) return;
|
||||
|
||||
var P = this.X + LineOffset( this.feeder.lineBuffers, this.Y ) + this.__off;
|
||||
|
||||
this.PStart = P;
|
||||
this.PEnd = P + 1;
|
||||
@ -538,6 +583,13 @@
|
||||
Cursor.prototype.suppressEvent = function() { ++ this.__suppEvt; };
|
||||
Cursor.prototype.unsuppressEvent = function() { -- this.__suppEvt; };
|
||||
|
||||
Cursor.prototype.__suppressUpdate = function() { ++ this.__suppUpdate; };
|
||||
Cursor.prototype.__unsuppressUpdate = function()
|
||||
{
|
||||
-- this.__suppUpdate;
|
||||
this.updatePosition();
|
||||
};
|
||||
|
||||
Cursor.prototype.getLine = function( display )
|
||||
{
|
||||
var feeder = this.feeder;
|
||||
@ -568,20 +620,7 @@
|
||||
|
||||
__readOnly( Cursor.prototype, "rawLine", function()
|
||||
{
|
||||
var str = this.feeder.content;
|
||||
var lineNum = this.getLine().lineNum - 1;
|
||||
var i = str.indexOf( "\n" ), j = 0;
|
||||
|
||||
for( ; 0 <= i; i = str.indexOf( "\n", i ), j ++ )
|
||||
{
|
||||
if( lineNum == j ) break;
|
||||
i ++;
|
||||
}
|
||||
|
||||
if( j == 0 && i == -1 ) i = 0;
|
||||
|
||||
var end = str.indexOf( "\n", i + 1 );
|
||||
return str.substring( i + 1, end );
|
||||
return this.feeder.line( this.getLine().lineNum - 1 );
|
||||
} );
|
||||
|
||||
// The position offset relative to current line
|
||||
|
@ -10,6 +10,7 @@
|
||||
var Cursor = ns[ NS_INVOKE ]( "Cursor" );
|
||||
|
||||
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
||||
var C_LINE = 0;
|
||||
|
||||
var Feeder = function( rows, cols )
|
||||
{
|
||||
@ -35,6 +36,7 @@
|
||||
this.cursor = new Cursor( this );
|
||||
this.dispatcher = new EventDispatcher();
|
||||
|
||||
this.__lineCache = [];
|
||||
this.__clseLine = null;
|
||||
this.__moreAt = -1;
|
||||
this.__rows = rows;
|
||||
@ -42,7 +44,7 @@
|
||||
|
||||
Feeder.prototype.init = function( content, wrap )
|
||||
{
|
||||
this.content = content;
|
||||
this.__content = content;
|
||||
this.setWrap( wrap );
|
||||
|
||||
this.firstBuffer.Push( content, this.wrap, 0 );
|
||||
@ -142,7 +144,7 @@
|
||||
if( Y < 0 ) Y = 0;
|
||||
|
||||
// Compensate the last "\n" content placeholder
|
||||
var cont = this.content.slice( 0, -1 );
|
||||
var cont = this.__content.slice( 0, -1 );
|
||||
if( 0 < Y )
|
||||
{
|
||||
f = cont.indexOf( "\n" );
|
||||
@ -158,7 +160,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
this.firstBuffer.Push( this.content.substr( f + 1 ), this.wrap, i );
|
||||
this.firstBuffer.Push( this.__content.substr( f + 1 ), this.wrap, i );
|
||||
|
||||
this.panX = X;
|
||||
this.panY = Y;
|
||||
@ -171,8 +173,27 @@
|
||||
this.__softRender();
|
||||
};
|
||||
|
||||
Feeder.prototype.line = function( n )
|
||||
{
|
||||
if( this.__lineCache[ n ] )
|
||||
return this.__lineCache[ n ];
|
||||
var str = this.__content;
|
||||
var i = str.indexOf( "\n" ), j = 0;
|
||||
|
||||
for( ; 0 <= i; i = str.indexOf( "\n", i ), j ++ )
|
||||
{
|
||||
if( n == j ) break;
|
||||
i ++;
|
||||
}
|
||||
|
||||
if( j == 0 && i == -1 ) i = 0;
|
||||
|
||||
var end = str.indexOf( "\n", i + 1 );
|
||||
return ( this.__lineCache[ n ] = str.substring( i + 1, end ) );
|
||||
};
|
||||
|
||||
__readOnly( Feeder.prototype, "linesTotal", function() {
|
||||
return occurence( this.content, "\n" );
|
||||
return occurence( this.__content, "\n" );
|
||||
} );
|
||||
|
||||
__readOnly( Feeder.prototype, "firstBuffer", function() {
|
||||
@ -216,7 +237,7 @@
|
||||
var i = l - X;
|
||||
do
|
||||
{
|
||||
if( this.content[ i + 1 ] == "\t" ) tabs ++;
|
||||
if( this.__content[ i + 1 ] == "\t" ) tabs ++;
|
||||
i ++;
|
||||
}
|
||||
while( i < l )
|
||||
@ -254,6 +275,15 @@
|
||||
return pos;
|
||||
} );
|
||||
|
||||
Object.defineProperty( Feeder.prototype, "content", {
|
||||
get: function() { return this.__content; }
|
||||
, set: function( v )
|
||||
{
|
||||
this.__lineCache = [];
|
||||
this.__content = v;
|
||||
}
|
||||
} );
|
||||
|
||||
__readOnly( Feeder.prototype, "linesOccupied", function() {
|
||||
var line = this.firstBuffer;
|
||||
if( line.placeholder ) return 0;
|
||||
|
31
botanjs/src/Components/Vim/State/Marks.js
Normal file
31
botanjs/src/Components/Vim/State/Marks.js
Normal file
@ -0,0 +1,31 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.State" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
var Keys = "'ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxy\"[]^.<>";
|
||||
|
||||
var Marks = function()
|
||||
{
|
||||
this.__marks = {};
|
||||
};
|
||||
|
||||
Marks.prototype.set = function( t, line, col )
|
||||
{
|
||||
if( Keys.indexOf( t ) == -1 ) return false;
|
||||
|
||||
this.__marks[ t ] = [ line, col ];
|
||||
return true;
|
||||
};
|
||||
|
||||
Marks.prototype.get = function( t )
|
||||
{
|
||||
return this.__marks[ t ];
|
||||
};
|
||||
|
||||
__readOnly( Marks, "Keys", function() { return Keys; } );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "Marks", Marks );
|
||||
|
||||
})();
|
@ -14,6 +14,8 @@
|
||||
|
||||
/** @type {Components.Vim.State.Registers} */
|
||||
var Registers = __import( "Components.Vim.State.Registers" );
|
||||
/** @type {Components.Vim.State.Marks} */
|
||||
var Marks = __import( "Components.Vim.State.Marks" );
|
||||
/** @type {Components.Vim.Syntax.Analyzer} */
|
||||
var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" );
|
||||
|
||||
@ -243,6 +245,7 @@
|
||||
this.statusFeeder = sfeeder;
|
||||
this.statusBar = statusBar;
|
||||
this.registers = new Registers();
|
||||
this.marks = new Marks();
|
||||
|
||||
this.__cursor = cfeeder.cursor;
|
||||
|
||||
|
@ -13,6 +13,8 @@ Components.Vim.Cursor.rec;
|
||||
/** @type Function */
|
||||
Components.Vim.Cursor.moveTo;
|
||||
/** @type Function */
|
||||
Components.Vim.Cursor.gotoLine;
|
||||
/** @type Function */
|
||||
Components.Vim.Cursor.moveX;
|
||||
/** @type Function */
|
||||
Components.Vim.Cursor.moveY;
|
||||
|
@ -43,6 +43,8 @@ Components.Vim.LineFeeder.linesOccupied;
|
||||
/** @type String */
|
||||
Components.Vim.LineFeeder.docPos;
|
||||
/** @type String */
|
||||
Components.Vim.LineFeeder.line;
|
||||
/** @type String */
|
||||
Components.Vim.LineFeeder.lineStat;
|
||||
/** @type {String} */
|
||||
Components.Vim.LineFeeder.content;
|
||||
|
10
botanjs/src/externs/Components.Vim.State.Marks.js
Normal file
10
botanjs/src/externs/Components.Vim.State.Marks.js
Normal file
@ -0,0 +1,10 @@
|
||||
/** @constructor */
|
||||
Components.Vim.State.Marks = function(){};
|
||||
|
||||
/** @type Function */
|
||||
Components.Vim.State.Marks.set;
|
||||
/** @type Function */
|
||||
Components.Vim.State.Marks.get;
|
||||
|
||||
/** @type String */
|
||||
Components.Vim.State.Marks.Keys;
|
@ -12,6 +12,11 @@ Components.Vim.VimArea.statusFeeder;
|
||||
/** @type {Components.Vim.StatusBar} */
|
||||
Components.Vim.VimArea.statusBar;
|
||||
|
||||
/** @type {Components.Vim.State.Registers} */
|
||||
Components.Vim.VimArea.registers;
|
||||
/** @type {Components.Vim.State.Marks} */
|
||||
Components.Vim.VimArea.marks;
|
||||
|
||||
/** @type Function */
|
||||
Components.Vim.VimArea.demo;
|
||||
/** @type Function */
|
||||
|
Loading…
Reference in New Issue
Block a user