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