reindentDocument method

void reindentDocument({
  1. required int newTabSize,
})

Implementation

void reindentDocument({required int newTabSize}) {
  final oldTabSize = detectIndentation();

  if (oldTabSize <= 0 || newTabSize <= 0 || oldTabSize == newTabSize) {
    tabSize = newTabSize;
    return;
  }

  final originalText = text;
  if (originalText.isEmpty) {
    tabSize = newTabSize;
    return;
  }

  final originalSelection = selection;
  final originalLines = originalText.split("\n");
  final newLines = <String>[];

  for (final line in originalLines) {
    final match = RegExp(r"^[ \t]+").firstMatch(line);
    if (match == null) {
      newLines.add(line);
      continue;
    }

    final leadingWhitespace = match.group(0)!;
    final content = line.substring(leadingWhitespace.length);

    int visualSpaces = 0;
    for (int i = 0; i < leadingWhitespace.length; i++) {
      if (leadingWhitespace[i] == '\t') {
        visualSpaces += oldTabSize - (visualSpaces % oldTabSize);
      } else {
        visualSpaces += 1;
      }
    }

    final indentLevels = visualSpaces ~/ oldTabSize;
    final remainder = visualSpaces % oldTabSize;
    final newIndentLength = (indentLevels * newTabSize) + remainder;

    newLines.add("${' ' * newIndentLength}$content");
  }

  final newText = newLines.join("\n");
  tabSize = newTabSize;

  if (newText == originalText) return;

  final newLineStarts = _lineStarts(newText);
  final originalLineStarts = _lineStarts(originalText);

  final mappedSelection = TextSelection(
    baseOffset: _mapOffsetForReindent(
      originalOffset: originalSelection.baseOffset,
      originalText: originalText,
      newText: newText,
      originalLineStarts: originalLineStarts,
      newLineStarts: newLineStarts,
    ),
    extentOffset: _mapOffsetForReindent(
      originalOffset: originalSelection.extentOffset,
      originalText: originalText,
      newText: newText,
      originalLineStarts: originalLineStarts,
      newLineStarts: newLineStarts,
    ),
  );

  text = newText;
  selection = mappedSelection;
}