textOutdentLines function

TextLineCommandResult textOutdentLines({
  1. required List<String> lines,
  2. required TextLineStateSnapshot state,
  3. int width = 2,
})

Implementation

TextLineCommandResult textOutdentLines({
  required List<String> lines,
  required TextLineStateSnapshot state,
  int width = 2,
}) {
  final nextLines = lines.isEmpty ? <String>[''] : List<String>.from(lines);
  final indentWidth = width < 1 ? 1 : width;
  final clampedState = _clampLineStateSnapshot(state, nextLines);
  final span = _selectedLineSpan(clampedState);
  final removalCounts = <int, int>{};
  var changed = false;

  for (var lineIndex = span.startLine; lineIndex <= span.endLine; lineIndex++) {
    final removalCount = _leadingIndentRemovalCount(
      nextLines[lineIndex],
      indentWidth,
    );
    removalCounts[lineIndex] = removalCount;
    changed = changed || removalCount > 0;
  }

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

  final editorState = EditorState();
  syncEditorStateFromLineSnapshot(
    editorState,
    clampedState,
    lineCount: nextLines.length,
    lineLength: (line) => nextLines[line].length,
  );

  final deltas = <int, int>{};
  for (var lineIndex = span.startLine; lineIndex <= span.endLine; lineIndex++) {
    final removalCount = removalCounts[lineIndex]!;
    if (removalCount == 0) continue;
    nextLines[lineIndex] = nextLines[lineIndex].substring(removalCount);
    deltas[lineIndex] = -removalCount;
  }

  editorState.applyColumnDeltas(
    deltas,
    lineLength: (line) => nextLines[line].length,
  );
  return _lineResultFromSnapshot(
    nextLines,
    lineSnapshotFromEditorState(
      editorState,
      lineCount: nextLines.length,
      lineLength: (line) => nextLines[line].length,
      preserveCollapsedSelection: true,
    ),
  );
}