@@ -2791,8 +2791,40 @@ export function initVim(CM) {
27912791 } ,
27922792 indent : function ( cm , args , ranges ) {
27932793 var vim = cm . state . vim ;
2794- var repeat = ( vim . visualMode ) ? ( args . repeat || 0 ) : 1 ;
2795- if ( cm . indentMore ) {
2794+ // In visual mode, n> shifts the selection right n times, instead of
2795+ // shifting n lines right once.
2796+ var repeat = vim . visualMode ? args . repeat || 1 : 1 ;
2797+ if ( vim . visualBlock ) {
2798+ var tabSize = cm . getOption ( 'tabSize' ) ;
2799+ var indent = cm . getOption ( 'indentWithTabs' ) ? '\t' : ' ' . repeat ( tabSize ) ;
2800+ var cursor ;
2801+ for ( var i = ranges . length - 1 ; i >= 0 ; i -- ) {
2802+ cursor = cursorMin ( ranges [ i ] . anchor , ranges [ i ] . head ) ;
2803+ if ( args . indentRight ) {
2804+ cm . replaceRange ( indent . repeat ( repeat ) , cursor , cursor ) ;
2805+ } else {
2806+ var text = cm . getLine ( cursor . line ) ;
2807+ var end = 0 ;
2808+ for ( var j = 0 ; j < repeat ; j ++ ) {
2809+ var ch = text [ cursor . ch + end ] ;
2810+ if ( ch == '\t' ) {
2811+ end ++ ;
2812+ } else if ( ch == ' ' ) {
2813+ end ++ ;
2814+ for ( var k = 1 ; k < indent . length ; k ++ ) {
2815+ ch = text [ cursor . ch + end ] ;
2816+ if ( ch !== ' ' ) break ;
2817+ end ++ ;
2818+ }
2819+ } else {
2820+ break
2821+ }
2822+ }
2823+ cm . replaceRange ( '' , cursor , offsetCursor ( cursor , 0 , end ) ) ;
2824+ }
2825+ }
2826+ return cursor ;
2827+ } else if ( cm . indentMore ) {
27962828 for ( var j = 0 ; j < repeat ; j ++ ) {
27972829 if ( args . indentRight ) cm . indentMore ( ) ;
27982830 else cm . indentLess ( ) ;
@@ -2802,8 +2834,6 @@ export function initVim(CM) {
28022834 var endLine = vim . visualBlock ?
28032835 ranges [ ranges . length - 1 ] . anchor . line :
28042836 ranges [ 0 ] . head . line ;
2805- // In visual mode, n> shifts the selection right n times, instead of
2806- // shifting n lines right once.
28072837 if ( args . linewise ) {
28082838 // The only way to delete a newline is to delete until the start of
28092839 // the next line, so in linewise mode evalInput will include the next
0 commit comments