Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move line autoindent#14390 #23248

Closed
76 changes: 76 additions & 0 deletions src/vs/editor/contrib/linesOperations/common/moveLinesCommand.ts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { ICommand, ICursorStateComputerData, IEditOperationBuilder, ITokenizedModel } from 'vs/editor/common/editorCommon';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import Strings = require('vs/base/common/strings');

export class MoveLinesCommand implements ICommand {

Expand All @@ -21,6 +23,17 @@ export class MoveLinesCommand implements ICommand {
this._isMovingDown = isMovingDown;
}

public static getBeginWhitespaces(string: string) {
return string.match(/^\s*/)[0] || '';
}

public static replaceLine(model: ITokenizedModel, builder: IEditOperationBuilder, lineNumber: number, newText: string) {
builder.addEditOperation(new Range(
lineNumber, 1,
lineNumber, model.getLineMaxColumn(lineNumber)
), newText);
}

public getEditOperations(model: ITokenizedModel, builder: IEditOperationBuilder): void {

var modelLineCount = model.getLineCount();
Expand Down Expand Up @@ -64,10 +77,50 @@ export class MoveLinesCommand implements ICommand {
var movingLineNumber: number,
movingLineText: string;

const options = model.getOptions();
let oneIndent = ' ';
if (options.insertSpaces) {
oneIndent = Array(options.tabSize).join(' ');
}

let bracketsSupport = LanguageConfigurationRegistry.getBracketsSupport(model.getLanguageIdentifier().id);
const lineComment = Strings.escapeRegExpCharacters(LanguageConfigurationRegistry.getComments(model.getLanguageIdentifier().id).lineCommentToken);
let brackets = [];
// If language have brackets, use them to detect blocks
if (bracketsSupport) {
brackets = bracketsSupport.brackets;
}

if (this._isMovingDown) {
movingLineNumber = s.endLineNumber + 1;
movingLineText = model.getLineContent(movingLineNumber);

let movingLineWhitespaces = MoveLinesCommand.getBeginWhitespaces(model.getLineContent(movingLineNumber));
const firstLineWhitespaces = MoveLinesCommand.getBeginWhitespaces(model.getLineContent(s.startLineNumber));
const lastLineWhitespaces = MoveLinesCommand.getBeginWhitespaces(model.getLineContent(s.endLineNumber));

// If selection have the same indentation for the first and last line, apply an auto indent to the selected block
if (firstLineWhitespaces.length === lastLineWhitespaces.length && movingLineText.length > 0) {
for (var lineNumber = s.startLineNumber; lineNumber <= s.endLineNumber; ++lineNumber) {
// If line end with language open bracket, use indentation of the next next line
let newMovingWhitespaces = movingLineWhitespaces;

const allOpenbrackets = Strings.escapeRegExpCharacters(brackets.map(x => x.open).reduce((x, y) => x + y, ''));

if (
movingLineText.match(new RegExp('[' + allOpenbrackets + ']\\s*(' + lineComment + '.*)?$')) &&
!movingLineText.match(new RegExp(lineComment + '.*[' + allOpenbrackets + ']\\s*(' + lineComment + '.*)?$'))
) {
newMovingWhitespaces += oneIndent;
}
// Replace the current line whitespaces with the moving line whitespaces
const lineText = model.getLineContent(lineNumber).replace(
new RegExp('^' + firstLineWhitespaces), newMovingWhitespaces
);
MoveLinesCommand.replaceLine(model, builder, lineNumber, lineText);
}
}

// Delete line that needs to be moved
builder.addEditOperation(new Range(movingLineNumber - 1, model.getLineMaxColumn(movingLineNumber - 1), movingLineNumber, model.getLineMaxColumn(movingLineNumber)), null);

Expand All @@ -77,6 +130,28 @@ export class MoveLinesCommand implements ICommand {
movingLineNumber = s.startLineNumber - 1;
movingLineText = model.getLineContent(movingLineNumber);

let movingLineWhitespaces = MoveLinesCommand.getBeginWhitespaces(model.getLineContent(movingLineNumber));
const firstLineWhitespaces = MoveLinesCommand.getBeginWhitespaces(model.getLineContent(s.startLineNumber));
const lastLineWhitespaces = MoveLinesCommand.getBeginWhitespaces(model.getLineContent(s.endLineNumber));

// If selection have the same indentation for the first and last line, apply an auto indent to the selected block
if (firstLineWhitespaces.length === lastLineWhitespaces.length && movingLineText.length > 0) {
for (var lineNumber = s.startLineNumber; lineNumber <= s.endLineNumber; ++lineNumber) {
// If line start with language closing bracket, use indentation of the next next line
const allClosingbrackets = Strings.escapeRegExpCharacters(brackets.map(x => x.close).reduce((x, y) => x + y, ''));
let newMovingWhitespaces = movingLineWhitespaces;

if (movingLineText.match(new RegExp('^\\s*[' + allClosingbrackets + ']'))) {
newMovingWhitespaces += oneIndent;
}
// Replace the current line whitespaces with the moving line whitespaces
const lineText = model.getLineContent(lineNumber).replace(
new RegExp('^' + firstLineWhitespaces), newMovingWhitespaces
);
MoveLinesCommand.replaceLine(model, builder, lineNumber, lineText);
}
}

// Delete line that needs to be moved
builder.addEditOperation(new Range(movingLineNumber, 1, movingLineNumber + 1, 1), null);

Expand All @@ -98,3 +173,4 @@ export class MoveLinesCommand implements ICommand {
return result;
}
}

Loading