forked from Botanical/BotanJS
Partial indent command
This commit is contained in:
parent
a3fa2e82d7
commit
78cb3d3610
@ -204,6 +204,9 @@
|
||||
{
|
||||
var ind = this.__phantomIndent;
|
||||
if( !this.__phantomIndent ) return;
|
||||
|
||||
debug.Info( "Realize Indentation: " + ind );
|
||||
|
||||
l = ind[ IN_END ];
|
||||
for( var i = ind[ IN_START ]; i < l; i ++ )
|
||||
{
|
||||
@ -261,6 +264,7 @@
|
||||
a[ IN_DEL ] = inDel;
|
||||
|
||||
this.__phantomIndent = a;
|
||||
debug.Info( "Phantom indent: " + a );
|
||||
}
|
||||
};
|
||||
|
||||
@ -269,6 +273,8 @@
|
||||
var ind = this.__phantomIndent;
|
||||
if( !ind ) return "";
|
||||
|
||||
debug.Info( "Erase phantom indent: " + ind );
|
||||
|
||||
var cur = this.__cursor;
|
||||
var feeder = cur.feeder;
|
||||
|
||||
|
@ -24,8 +24,10 @@
|
||||
var stack = this.__cursor.rec.redo();
|
||||
if( stack )
|
||||
{
|
||||
this.__cursor.suppressEvent();
|
||||
stack.play();
|
||||
this.__message = "<<TODO>>; before #" + stack.id + " " + stack.time;
|
||||
this.__cursor.unsuppressEvent();
|
||||
this.__message = Mesg( "NCHANGES", "<TODO>", stack.id, stack.time );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -92,7 +92,7 @@
|
||||
this.__cursor.unsuppressEvent();
|
||||
};
|
||||
|
||||
REPLACE.prototype.handler = function( e, p, range )
|
||||
REPLACE.prototype.handler = function( e, p )
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
@ -143,13 +143,16 @@
|
||||
var content = feeder.content.slice( 0, -1 )
|
||||
.replace( search, this.__replCallback ) + "\n";
|
||||
|
||||
if( !this.__replacedGroups.length )
|
||||
var numSubs = this.__replacedGroups.length;
|
||||
if( !numSubs )
|
||||
{
|
||||
this.__msg = VimError( "E486", spattern.join( "" ) );
|
||||
}
|
||||
|
||||
feeder.content = content;
|
||||
|
||||
this.__msg = Mesg( "REPLACE", numSubs, "<TODO>" );
|
||||
|
||||
// Record this step for UNDO / REDO
|
||||
this.__rec();
|
||||
|
||||
|
242
botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
Normal file
242
botanjs/src/Components/Vim/Actions/SHIFT_LINES.js
Normal file
@ -0,0 +1,242 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Vim.Actions" );
|
||||
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
var beep = __import( "Components.Vim.Beep" );
|
||||
|
||||
/** @type {Components.Vim.State.Stack} */
|
||||
var Stack = __import( "Components.Vim.State.Stack" );
|
||||
|
||||
var VimError = __import( "Components.Vim.Error" );
|
||||
var Mesg = __import( "Components.Vim.Message" );
|
||||
|
||||
var occurence = __import( "System.utils.Perf.CountSubstr" );
|
||||
|
||||
var REPL_BEFORE = 0;
|
||||
var REPL_OFFSET = 1;
|
||||
var REPL_LENGTH = 2;
|
||||
|
||||
/** @type {Components.Vim.IAction}
|
||||
* Cursor @param {Components.Vim.Cursor}
|
||||
* e @param {Components.Vim.ActionEvent}
|
||||
**/
|
||||
var SHIFT_LINES = function( Cursor, e )
|
||||
{
|
||||
/** @type {Components.Vim.Cursor} */
|
||||
this.__cursor = Cursor;
|
||||
this.__startX = Cursor.aPos;
|
||||
this.__msg = "<LINE_SHIFT>";
|
||||
|
||||
this.__slineNum = Cursor.getLine().lineNum;
|
||||
|
||||
this.__lines = e.count;
|
||||
debug.Info( "Open shift: " + this.__lines + " line(s) below the cursor" );
|
||||
|
||||
this.__direction = e.kMap( ">" ) ? 1 : -1;
|
||||
debug.Info( "Direction is: " + ( this.__direction == 1 ? ">" : "<" ) );
|
||||
|
||||
Cursor.suppressEvent();
|
||||
};
|
||||
|
||||
SHIFT_LINES.prototype.allowMovement = true;
|
||||
|
||||
SHIFT_LINES.prototype.dispose = function()
|
||||
{
|
||||
this.__cursor.unsuppressEvent();
|
||||
};
|
||||
|
||||
SHIFT_LINES.prototype.handler = function( e, sp )
|
||||
{
|
||||
e.preventDefault();
|
||||
|
||||
if( e.ModKeys || e.kMap( "i" ) ) return;
|
||||
|
||||
var cur = this.__cursor;
|
||||
var feeder = cur.feeder;
|
||||
|
||||
var Triggered = false;
|
||||
var dir = this.__direction;
|
||||
|
||||
var start = this.__slineNum;
|
||||
var nline = this.__lines;
|
||||
|
||||
if( 1 < e.count )
|
||||
{
|
||||
nline += e.count;
|
||||
}
|
||||
|
||||
var end = start;
|
||||
|
||||
var shiftCount = 1;
|
||||
if( sp == undefined )
|
||||
{
|
||||
Triggered = true;
|
||||
|
||||
sp = this.__startX;
|
||||
|
||||
var currAp = cur.aPos;
|
||||
|
||||
if( this.__startX != currAp )
|
||||
{
|
||||
if( e.kMap( "h" ) || e.kMap( "l" ) ){}
|
||||
else if( e.kMap( "j" ) )
|
||||
{
|
||||
end = start + nline;
|
||||
}
|
||||
else if( e.kMap( "k" ) )
|
||||
{
|
||||
start -= nline;
|
||||
}
|
||||
else // TODO: Dectect movement line count
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !( ( 0 < dir && ( e.kMap( ">" ) || e.kMap( "l" ) ) )
|
||||
|| ( dir < 0 && ( e.kMap( "<" ) || e.kMap( "h" ) ) )
|
||||
) )
|
||||
{
|
||||
beep();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// last "\n" padding
|
||||
var c = feeder.content.slice( 0, -1 );
|
||||
|
||||
var indents = c.match( /^[\t ]+/gm );
|
||||
var indentChar = "\t";
|
||||
var tabwidth = feeder.firstBuffer.tabWidth;
|
||||
|
||||
if( indents )
|
||||
{
|
||||
var l = indents.length - 1;
|
||||
|
||||
if( 1 < l )
|
||||
{
|
||||
debug.Info( "Guessing the tabstop:" );
|
||||
var tabOccr = 0;
|
||||
var spOccr = 0;
|
||||
|
||||
// Guess indent
|
||||
var tabStat = {};
|
||||
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
var ind = indents[ i ];
|
||||
var indNext = indents[ i + 1 ];
|
||||
tabOccr += occurence( ind, "\t" );
|
||||
spOccr += occurence( ind, " " );
|
||||
var d = indNext.length - ind.length;
|
||||
if( d == 0 ) continue;
|
||||
|
||||
d = d < 0 ? -d : d;
|
||||
|
||||
if( !tabStat[ d ] ) tabStat[ d ] = 0;
|
||||
|
||||
tabStat[ d ] ++;
|
||||
}
|
||||
|
||||
var upperDiff = 0;
|
||||
var indentCLen = 0;
|
||||
for( var i in tabStat )
|
||||
{
|
||||
var p = tabStat[ i ];
|
||||
if( upperDiff < p )
|
||||
{
|
||||
upperDiff = p;
|
||||
indentCLen = i;
|
||||
}
|
||||
}
|
||||
|
||||
spOccr /= indentCLen;
|
||||
|
||||
if( tabOccr < spOccr )
|
||||
{
|
||||
indentChar = "";
|
||||
for( var i = 0; i < indentCLen; i ++ ) indentChar += " ";
|
||||
}
|
||||
|
||||
tabwidth = indentCLen;
|
||||
|
||||
debug.Info( "\tTab count: " + tabOccr );
|
||||
debug.Info( "\tSpace count: " + spOccr );
|
||||
debug.Info( "\ti.e. indent using " + JSON.stringify( indentChar ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug.Info( "Not enough tabs to determine the tabstop, using default" );
|
||||
}
|
||||
}
|
||||
|
||||
debug.Info( "Start: " + start, "End: " + end );
|
||||
var rBlock = "";
|
||||
|
||||
var started = false;
|
||||
var indentTimes = 1;
|
||||
|
||||
feeder.content = "";
|
||||
nline = 0;
|
||||
|
||||
for( var i = 0, j = 0; 0 <= i; i = c.indexOf( "\n", i ), j ++ )
|
||||
{
|
||||
i ++;
|
||||
|
||||
if( j < start ) continue;
|
||||
else if( !started )
|
||||
{
|
||||
started = true;
|
||||
feeder.content = c.substring( 0, i - 1 );
|
||||
}
|
||||
|
||||
if( end < j ) break;
|
||||
|
||||
var line = c.substring( 1 < i ? i : i - 1, c.indexOf( "\n", i ) );
|
||||
|
||||
if( 1 < i ) feeder.content += "\n";
|
||||
|
||||
if( line !== "" )
|
||||
{
|
||||
if( 0 < dir )
|
||||
{
|
||||
feeder.content += indentChar + line;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( var si = 0, sj = 1; si < indentTimes; si ++ )
|
||||
{
|
||||
var startC = line[ si ];
|
||||
if( startC == " " )
|
||||
{
|
||||
for( ; sj < tabwidth; sj ++ )
|
||||
{
|
||||
if( !~"\t ".indexOf( line[ si + sj ] ) ) break;
|
||||
}
|
||||
}
|
||||
else if( startC != "\t" ) break;
|
||||
}
|
||||
|
||||
feeder.content += line.substring( si + sj - 1 );
|
||||
}
|
||||
nline ++;
|
||||
}
|
||||
}
|
||||
|
||||
feeder.content += "\n" + c.substring( i ) + "\n";
|
||||
feeder.pan();
|
||||
|
||||
this.__msg = Mesg( "LINES_SHIFTED", nline, dir < 0 ? "<" : ">", 1 );
|
||||
|
||||
return Triggered;
|
||||
};
|
||||
|
||||
SHIFT_LINES.prototype.getMessage = function()
|
||||
{
|
||||
return this.__msg;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "SHIFT_LINES", SHIFT_LINES );
|
||||
})();
|
@ -24,8 +24,10 @@
|
||||
var stack = this.__cursor.rec.undo();
|
||||
if( stack )
|
||||
{
|
||||
this.__cursor.suppressEvent();
|
||||
stack.play();
|
||||
this.__message = "<<TODO>>; before #" + stack.id + " " + stack.time;
|
||||
this.__cursor.unsuppressEvent();
|
||||
this.__message = Mesg( "NCHANGES", "<TODO>", stack.id, stack.time );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -50,22 +50,18 @@
|
||||
var currAp = cur.aPos;
|
||||
if( this.__startX != currAp )
|
||||
{
|
||||
// Remove to start
|
||||
if( e.kMap( "^" ) )
|
||||
{
|
||||
sp --;
|
||||
}
|
||||
// Remove char in cursor
|
||||
else if( e.kMap( "l" ) )
|
||||
{
|
||||
cur.moveX( -1 );
|
||||
}
|
||||
// Remove char before cursor
|
||||
else if( e.kMap( "h" ) )
|
||||
{
|
||||
sp = currAp;
|
||||
}
|
||||
// Remove the current and the following line
|
||||
else if( e.kMap( "j" ) )
|
||||
{
|
||||
newLine = true;
|
||||
@ -75,7 +71,6 @@
|
||||
cur.lineStart();
|
||||
this.__startX = cur.aPos;
|
||||
}
|
||||
// Remove the current and the preceding line
|
||||
else if( e.kMap( "k" ) )
|
||||
{
|
||||
newLine = true;
|
||||
@ -94,7 +89,6 @@
|
||||
cur.moveTo( this.__startX );
|
||||
}
|
||||
}
|
||||
// Remove the current line
|
||||
else
|
||||
{
|
||||
if( e.kMap( "y" ) )
|
||||
@ -111,8 +105,6 @@
|
||||
}
|
||||
else if( e.kMap( "^" ) )
|
||||
{
|
||||
// Do nothing as nothing can be removed
|
||||
// since there is no successful movement
|
||||
return true;
|
||||
}
|
||||
// this is the same as kMap( "h" ) above
|
||||
|
@ -205,7 +205,7 @@
|
||||
case A: // Append
|
||||
ccur.moveX( 1, true, true );
|
||||
case I: // Insert
|
||||
ccur.openAction( "INSERT" );
|
||||
ccur.openAction( "INSERT", e );
|
||||
break;
|
||||
|
||||
case S: // Delete Char and start insert
|
||||
@ -213,18 +213,18 @@
|
||||
{
|
||||
ccur.openRunAction( "DELETE", e, ccur.aPos );
|
||||
}
|
||||
ccur.openAction( "INSERT" );
|
||||
ccur.openAction( "INSERT", e );
|
||||
break;
|
||||
|
||||
case SHIFT + O: // new line before insert
|
||||
ccur.lineStart();
|
||||
ccur.openAction( "INSERT" );
|
||||
ccur.openAction( "INSERT", e );
|
||||
ccur.action.handler( new ActionEvent( e.sender, "Enter" ) );
|
||||
ccur.moveY( -1 );
|
||||
break;
|
||||
case O: // new line insert
|
||||
ccur.lineEnd( true );
|
||||
ccur.openAction( "INSERT" );
|
||||
ccur.openAction( "INSERT", e );
|
||||
ccur.action.handler( new ActionEvent( e.sender, "Enter" ) );
|
||||
break;
|
||||
|
||||
@ -236,10 +236,10 @@
|
||||
break;
|
||||
|
||||
case D: // Del with motion
|
||||
ccur.openAction( "DELETE" );
|
||||
ccur.openAction( "DELETE", e );
|
||||
break;
|
||||
case Y: // Yank with motion
|
||||
ccur.openAction( "YANK" );
|
||||
ccur.openAction( "YANK", e );
|
||||
break;
|
||||
|
||||
case P: // Put
|
||||
@ -272,7 +272,7 @@
|
||||
|
||||
case V: // Visual
|
||||
case SHIFT + V: // Visual line
|
||||
ccur.openAction( "VISUAL" );
|
||||
ccur.openAction( "VISUAL", e );
|
||||
ccur.action.handler( e );
|
||||
break;
|
||||
|
||||
@ -281,6 +281,11 @@
|
||||
this.__divedCCmd.handler( e );
|
||||
break;
|
||||
|
||||
case SHIFT + COMMA: // <
|
||||
case SHIFT + FULLSTOP: // >
|
||||
ccur.openAction( "SHIFT_LINES", e );
|
||||
break;
|
||||
|
||||
case F1: // F1, help
|
||||
break;
|
||||
default:
|
||||
@ -349,15 +354,21 @@
|
||||
var Count = e.key;
|
||||
var recurNum = function( e )
|
||||
{
|
||||
var intercept = e.ModKeys;
|
||||
switch( e.keyCode )
|
||||
{
|
||||
case _0: case _1: case _2:
|
||||
case _3: case _4: case _5:
|
||||
case _6: case _7: case _8: case _9:
|
||||
Count += e.key;
|
||||
_self.__composite( e, recurNum, ANY_KEY );
|
||||
e.cancel();
|
||||
return;
|
||||
intercept = true;
|
||||
}
|
||||
|
||||
if( intercept )
|
||||
{
|
||||
_self.__composite( e, recurNum, ANY_KEY );
|
||||
e.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
e.__count = Number( Count );
|
||||
|
@ -376,13 +376,13 @@
|
||||
|
||||
// Open an action handler
|
||||
// i.e. YANK, VISUAL, INSERT, UNDO, etc.
|
||||
Cursor.prototype.openAction = function( name )
|
||||
Cursor.prototype.openAction = function( name, e )
|
||||
{
|
||||
if( this.action ) this.action.dispose();
|
||||
|
||||
debug.Info( "openAction: " + name );
|
||||
|
||||
this.action = new (Actions[ name ])( this );
|
||||
this.action = new (Actions[ name ])( this, e );
|
||||
this.__pulseMsg = null;
|
||||
|
||||
this.__visualUpdate();
|
||||
|
@ -19,10 +19,12 @@ VIMRE_VERSION = "1.0.0b";
|
||||
|
||||
, "UNDO_LIMIT": "Already at oldest change"
|
||||
, "REDO_LIMIT": "Already at newest change"
|
||||
, "NCHANGES": "%1 change(s); before #%2 %3"
|
||||
|
||||
, "LINES_FEWER": "%1 fewer line(s)"
|
||||
, "LINES_MORE": "%1 more line(s)"
|
||||
, "LINES_YANKED": "%1 line(s) yanked"
|
||||
, "LINES_SHIFTED": "%1 line(s) %2ed %3 time(s)"
|
||||
|
||||
, "SEARCH_HIT_BOTTOM": "search hit BOTTOM, continuing at TOP"
|
||||
, "SEARCH_HIT_TOP": "search hit TOP, continuing at BOTTOM"
|
||||
|
Loading…
Reference in New Issue
Block a user