From 3eaf667c3f8cd2d98104b3532f45e00619981716 Mon Sep 17 00:00:00 2001 From: Harutyun Amirjanyan Date: Thu, 28 Nov 2024 19:21:45 +0400 Subject: [PATCH] vim indent in visualBlock mode (#5684) --- src/keyboard/vim.js | 39 ++++++++++++++++++++++++++++++++++----- src/keyboard/vim_test.js | 10 +++++++++- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/keyboard/vim.js b/src/keyboard/vim.js index 2fba401081d..f057eb5984d 100644 --- a/src/keyboard/vim.js +++ b/src/keyboard/vim.js @@ -3392,8 +3392,40 @@ domLib.importCssString(`.normal-mode .ace_cursor{ }, indent: function(cm, args, ranges) { var vim = cm.state.vim; - if (cm.indentMore) { - var repeat = (vim.visualMode) ? args.repeat : 1; + // In visual mode, n> shifts the selection right n times, instead of + // shifting n lines right once. + var repeat = (vim.visualMode) ? args.repeat : 1; + if (vim.visualBlock) { + var tabSize = cm.getOption('tabSize'); + var indent = cm.getOption('indentWithTabs') ? '\t' : ' '.repeat(tabSize); + var cursor; + for (var i = ranges.length - 1; i >= 0; i--) { + cursor = cursorMin(ranges[i].anchor, ranges[i].head); + if (args.indentRight) { + cm.replaceRange(indent.repeat(repeat), cursor, cursor); + } else { + var text = cm.getLine(cursor.line); + var end = 0; + for (var j = 0; j < repeat; j++) { + var ch = text[cursor.ch + end]; + if (ch == '\t') { + end++; + } else if (ch == ' ') { + end++; + for (var k = 1; k < indent.length; k++) { + ch = text[cursor.ch + end]; + if (ch !== ' ') break; + end++; + } + } else { + break + } + } + cm.replaceRange('', cursor, offsetCursor(cursor, 0, end)); + } + } + return cursor; + } else if (cm.indentMore) { for (var j = 0; j < repeat; j++) { if (args.indentRight) cm.indentMore(); else cm.indentLess(); @@ -3403,9 +3435,6 @@ domLib.importCssString(`.normal-mode .ace_cursor{ var endLine = vim.visualBlock ? ranges[ranges.length - 1].anchor.line : ranges[0].head.line; - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = (vim.visualMode) ? args.repeat : 1; if (args.linewise) { // The only way to delete a newline is to delete until the start of // the next line, so in linewise mode evalInput will include the next diff --git a/src/keyboard/vim_test.js b/src/keyboard/vim_test.js index 58bafd12912..65d302596f3 100644 --- a/src/keyboard/vim_test.js +++ b/src/keyboard/vim_test.js @@ -1571,7 +1571,15 @@ testVim('=', function(cm, vim, helpers) { var expectedValue = 'word1\nword2\nword3'; helpers.doKeys('='); eq(expectedValue, cm.getValue()); -}, { value: ' word1\n word2\n word3', indentUnit: 2 }); +}, { value: ' word1\n word2\n word3', indentUnit: 2 }); +testVim('>', 'j', 'j'); + helpers.doKeys('4', '>'); + eq(' word 1\n word 2\n word 3', cm.getValue()); + helpers.doKeys('g', 'v', '14', '<'); + eq(' word1\n word2\n word3', cm.getValue()); +}, { value: ' word1\n word2\n word3', indentUnit: 2 }); // Edit tests