textCleanupWhitespace function

TextLineCommandResult textCleanupWhitespace({
  1. required List<String> lines,
  2. required TextLineStateSnapshot state,
  3. bool trimTrailingBlankLines = true,
})

Implementation

TextLineCommandResult textCleanupWhitespace({
  required List<String> lines,
  required TextLineStateSnapshot state,
  bool trimTrailingBlankLines = true,
}) {
  final nextLines = lines.isEmpty ? <String>[''] : List<String>.from(lines);
  final clampedState = _clampLineStateSnapshot(state, nextLines);
  final hasSelection = clampedState.hasSelection;
  final span = hasSelection
      ? _selectedLineSpan(clampedState)
      : (startLine: 0, endLine: nextLines.length - 1);
  final trimmedLengths = <int, int>{};
  var changed = false;

  for (var lineIndex = span.startLine; lineIndex <= span.endLine; lineIndex++) {
    final trimmedLength = _trailingHorizontalTrimLength(nextLines[lineIndex]);
    trimmedLengths[lineIndex] = trimmedLength;
    changed = changed || trimmedLength != nextLines[lineIndex].length;
  }

  var removedTrailingLines = 0;
  if (!hasSelection && trimTrailingBlankLines) {
    var lineIndex = nextLines.length - 1;
    while (lineIndex > 0 && trimmedLengths[lineIndex] == 0) {
      removedTrailingLines++;
      lineIndex--;
    }
    changed = changed || removedTrailingLines > 0;
  }

  if (!changed) {
    return _lineResultFromSnapshot(nextLines, clampedState, changed: false);
  }

  for (var lineIndex = span.startLine; lineIndex <= span.endLine; lineIndex++) {
    final trimmedLength = trimmedLengths[lineIndex]!;
    nextLines[lineIndex] = nextLines[lineIndex].substring(0, trimmedLength);
  }

  if (!hasSelection && removedTrailingLines > 0) {
    nextLines.removeRange(
      nextLines.length - removedTrailingLines,
      nextLines.length,
    );
  }

  final nextCursor = clampedState.cursor.line >= nextLines.length
      ? TextPosition(line: nextLines.length - 1, column: nextLines.last.length)
      : clampedState.cursor;
  final nextState = hasSelection
      ? TextLineStateSnapshot.selection(
          base: clampedState.selectionBase!,
          extent: clampedState.selectionExtent!,
          cursor: nextCursor,
          preserveCollapsedSelection: true,
        )
      : TextLineStateSnapshot.collapsed(cursor: nextCursor);
  return _lineResultFromSnapshot(nextLines, nextState);
}