Added :{number} support

This commit is contained in:
斟酌 鵬兄 2017-03-17 13:34:31 +08:00
parent 68ee6dacc6
commit 1511c70957
12 changed files with 313 additions and 37 deletions

View File

@ -79,6 +79,9 @@
case "registers": case "registers":
out[ CMD_TYPE ] = "REGISTERS"; out[ CMD_TYPE ] = "REGISTERS";
break; break;
case "marks":
out[ CMD_TYPE ] = "MARKS";
break;
case "ver": case "ver":
case "version": case "version":
out[ CMD_TYPE ] = "VERSION"; out[ CMD_TYPE ] = "VERSION";
@ -90,6 +93,13 @@
case "varec": case "varec":
out[ CMD_TYPE ] = "VA_REC"; out[ CMD_TYPE ] = "VA_REC";
break; break;
case "": // Range jumping
pattern.push( true );
case "p":
allowRange = true;
out[ CMD_TYPE ] = "PRINT";
break;
} }
if( range !== "" ) if( range !== "" )

View 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 );
})();

View 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 );
})();

View File

@ -478,16 +478,17 @@
{ {
var kCode = e.keyCode; var kCode = e.keyCode;
if( this.__cMovement ) if( this.__captureComp )
{ {
if( !e.ModKeys ) if( !e.ModKeys )
{ {
this.__composite( e ); this.__composite( e );
this.__cMovement = false; this.__captureComp = false;
return true; return true;
} }
} }
var inst = this.__vimArea;
var ccur = this.__ccur; var ccur = this.__ccur;
var cfeeder = ccur.feeder; var cfeeder = ccur.feeder;
@ -610,10 +611,22 @@
break; 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 SHIFT + T: // To
case T: // To case T: // To
this.__cMovement = true; this.__captureComp = true;
this.__composite( e, function( e2 ) { this.__composite( e, function( e2 ) {
var oX = ccur.X; var oX = ccur.X;
@ -632,7 +645,7 @@
break; break;
case SHIFT + F: // To case SHIFT + F: // To
case F: // To case F: // To
this.__cMovement = true; this.__captureComp = true;
this.__composite( e, function( e2 ) { this.__composite( e, function( e2 ) {
ccur.openRunAction( "TO", e, e2 ); ccur.openRunAction( "TO", e, e2 );
@ -659,7 +672,7 @@
var analyzer = this.__vimArea.contentAnalyzer; var analyzer = this.__vimArea.contentAnalyzer;
this.__cMovement = true; this.__captureComp = true;
// Word boundary // Word boundary
this.__composite( e, function( e2 ) { this.__composite( e, function( e2 ) {
@ -703,7 +716,7 @@
case G: case G:
this.__cMovement = true; this.__captureComp = true;
// Go to top // Go to top
this.__composite( e, function() { this.__composite( e, function() {
@ -775,7 +788,7 @@
break; break;
case SLASH: // "/" Search movement case SLASH: // "/" Search movement
this.__cMovement = true; this.__captureComp = true;
this.__divedCCmd = new ExCommand( ccur, "/" ); this.__divedCCmd = new ExCommand( ccur, "/" );
this.__divedCCmd.handler( e ); this.__divedCCmd.handler( e );
@ -788,7 +801,7 @@
break; break;
} }
this.__cMovement = true; this.__captureComp = true;
var exCmd = new ExCommand( ccur, ":" ); var exCmd = new ExCommand( ccur, ":" );
exCmd.handler( e ); exCmd.handler( e );
@ -827,7 +840,7 @@
if( e.Escape ) if( e.Escape )
{ {
var b = false; var b = false;
this.__cMovement = false; this.__captureComp = false;
if( this.__compositeReg ) if( this.__compositeReg )
{ {
@ -853,7 +866,7 @@
if( this.__divedCCmd.handler( e ) ) if( this.__divedCCmd.handler( e ) )
{ {
this.__divedCCmd.dispose(); this.__divedCCmd.dispose();
this.__cMovement = false; this.__captureComp = false;
this.__divedCCmd = null; this.__divedCCmd = null;
return; return;
} }
@ -864,7 +877,7 @@
var cfeeder = this.__cfeeder; var cfeeder = this.__cfeeder;
var ccur = this.__ccur; var ccur = this.__ccur;
if( !this.__cMovement && ( !ccur.action || ccur.action.allowMovement ) ) if( !this.__captureComp && ( !ccur.action || ccur.action.allowMovement ) )
{ {
this.__modCommand( e ); this.__modCommand( e );
if( e.canceled ) return; if( e.canceled ) return;

View File

@ -106,6 +106,8 @@
// Move to an absolute position // Move to an absolute position
Cursor.prototype.moveTo = function( aPos, phantomSpace, skipTabs ) Cursor.prototype.moveTo = function( aPos, phantomSpace, skipTabs )
{ {
this.__suppressUpdate();
var content = this.feeder.content; var content = this.feeder.content;
var pline = this.getLine(); var pline = this.getLine();
var lastLineNum = pline.lineNum; var lastLineNum = pline.lineNum;
@ -131,10 +133,7 @@
} }
var jumpY = expLineNum - lastLineNum; var jumpY = expLineNum - lastLineNum;
if( jumpY ) if( jumpY ) this.moveY( jumpY );
{
this.moveY( jumpY );
}
pline = this.getLine(); pline = this.getLine();
@ -163,6 +162,50 @@
this.moveX( - Number.MAX_VALUE, false, false, true ); this.moveX( - Number.MAX_VALUE, false, false, true );
this.moveX( jumpX, false, phantomSpace, skipTabs ); 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 ) // 0 will be treated as default ( 1 )
@ -323,7 +366,7 @@
else if( c == "\n" ) else if( c == "\n" )
{ {
x += d; x += d;
} }
// Wordwrap phantomSpace movement compensation on max filled lines // Wordwrap phantomSpace movement compensation on max filled lines
if( feeder.wrap && boundary && !hasPhantomSpace && phantomSpace ) if( feeder.wrap && boundary && !hasPhantomSpace && phantomSpace )
@ -369,10 +412,12 @@
this.moveX( Number.MAX_VALUE, false, phantomSpace, true ); this.moveX( Number.MAX_VALUE, false, phantomSpace, true );
}; };
// Because LineOffset is costly, suppress unnecessary calls
Cursor.prototype.updatePosition = function() Cursor.prototype.updatePosition = function()
{ {
var feeder = this.feeder; if( 0 < this.__suppUpdate ) return;
var P = this.X + LineOffset( feeder.lineBuffers, this.Y ) + this.__off;
var P = this.X + LineOffset( this.feeder.lineBuffers, this.Y ) + this.__off;
this.PStart = P; this.PStart = P;
this.PEnd = P + 1; this.PEnd = P + 1;
@ -538,6 +583,13 @@
Cursor.prototype.suppressEvent = function() { ++ this.__suppEvt; }; Cursor.prototype.suppressEvent = function() { ++ this.__suppEvt; };
Cursor.prototype.unsuppressEvent = 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 ) Cursor.prototype.getLine = function( display )
{ {
var feeder = this.feeder; var feeder = this.feeder;
@ -568,20 +620,7 @@
__readOnly( Cursor.prototype, "rawLine", function() __readOnly( Cursor.prototype, "rawLine", function()
{ {
var str = this.feeder.content; return this.feeder.line( this.getLine().lineNum - 1 );
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 );
} ); } );
// The position offset relative to current line // The position offset relative to current line

View File

@ -10,6 +10,7 @@
var Cursor = ns[ NS_INVOKE ]( "Cursor" ); var Cursor = ns[ NS_INVOKE ]( "Cursor" );
var occurence = __import( "System.utils.Perf.CountSubstr" ); var occurence = __import( "System.utils.Perf.CountSubstr" );
var C_LINE = 0;
var Feeder = function( rows, cols ) var Feeder = function( rows, cols )
{ {
@ -35,6 +36,7 @@
this.cursor = new Cursor( this ); this.cursor = new Cursor( this );
this.dispatcher = new EventDispatcher(); this.dispatcher = new EventDispatcher();
this.__lineCache = [];
this.__clseLine = null; this.__clseLine = null;
this.__moreAt = -1; this.__moreAt = -1;
this.__rows = rows; this.__rows = rows;
@ -42,7 +44,7 @@
Feeder.prototype.init = function( content, wrap ) Feeder.prototype.init = function( content, wrap )
{ {
this.content = content; this.__content = content;
this.setWrap( wrap ); this.setWrap( wrap );
this.firstBuffer.Push( content, this.wrap, 0 ); this.firstBuffer.Push( content, this.wrap, 0 );
@ -142,7 +144,7 @@
if( Y < 0 ) Y = 0; if( Y < 0 ) Y = 0;
// Compensate the last "\n" content placeholder // Compensate the last "\n" content placeholder
var cont = this.content.slice( 0, -1 ); var cont = this.__content.slice( 0, -1 );
if( 0 < Y ) if( 0 < Y )
{ {
f = cont.indexOf( "\n" ); 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.panX = X;
this.panY = Y; this.panY = Y;
@ -171,8 +173,27 @@
this.__softRender(); 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() { __readOnly( Feeder.prototype, "linesTotal", function() {
return occurence( this.content, "\n" ); return occurence( this.__content, "\n" );
} ); } );
__readOnly( Feeder.prototype, "firstBuffer", function() { __readOnly( Feeder.prototype, "firstBuffer", function() {
@ -216,7 +237,7 @@
var i = l - X; var i = l - X;
do do
{ {
if( this.content[ i + 1 ] == "\t" ) tabs ++; if( this.__content[ i + 1 ] == "\t" ) tabs ++;
i ++; i ++;
} }
while( i < l ) while( i < l )
@ -254,6 +275,15 @@
return pos; 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() { __readOnly( Feeder.prototype, "linesOccupied", function() {
var line = this.firstBuffer; var line = this.firstBuffer;
if( line.placeholder ) return 0; if( line.placeholder ) return 0;

View 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 );
})();

View File

@ -14,6 +14,8 @@
/** @type {Components.Vim.State.Registers} */ /** @type {Components.Vim.State.Registers} */
var Registers = __import( "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} */ /** @type {Components.Vim.Syntax.Analyzer} */
var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" ); var SyntaxAnalyzer = __import( "Components.Vim.Syntax.Analyzer" );
@ -243,6 +245,7 @@
this.statusFeeder = sfeeder; this.statusFeeder = sfeeder;
this.statusBar = statusBar; this.statusBar = statusBar;
this.registers = new Registers(); this.registers = new Registers();
this.marks = new Marks();
this.__cursor = cfeeder.cursor; this.__cursor = cfeeder.cursor;

View File

@ -13,6 +13,8 @@ Components.Vim.Cursor.rec;
/** @type Function */ /** @type Function */
Components.Vim.Cursor.moveTo; Components.Vim.Cursor.moveTo;
/** @type Function */ /** @type Function */
Components.Vim.Cursor.gotoLine;
/** @type Function */
Components.Vim.Cursor.moveX; Components.Vim.Cursor.moveX;
/** @type Function */ /** @type Function */
Components.Vim.Cursor.moveY; Components.Vim.Cursor.moveY;

View File

@ -43,6 +43,8 @@ Components.Vim.LineFeeder.linesOccupied;
/** @type String */ /** @type String */
Components.Vim.LineFeeder.docPos; Components.Vim.LineFeeder.docPos;
/** @type String */ /** @type String */
Components.Vim.LineFeeder.line;
/** @type String */
Components.Vim.LineFeeder.lineStat; Components.Vim.LineFeeder.lineStat;
/** @type {String} */ /** @type {String} */
Components.Vim.LineFeeder.content; Components.Vim.LineFeeder.content;

View 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;

View File

@ -12,6 +12,11 @@ Components.Vim.VimArea.statusFeeder;
/** @type {Components.Vim.StatusBar} */ /** @type {Components.Vim.StatusBar} */
Components.Vim.VimArea.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 */ /** @type Function */
Components.Vim.VimArea.demo; Components.Vim.VimArea.demo;
/** @type Function */ /** @type Function */