toggleNumberedList function

TextLineCommandResult toggleNumberedList(
  1. List<String> lines, {
  2. required TextPosition cursor,
  3. TextPosition? selectionBase,
  4. TextPosition? selectionExtent,
  5. int startAt = 1,
})

Implementation

TextLineCommandResult toggleNumberedList(
  List<String> lines, {
  required TextPosition cursor,
  TextPosition? selectionBase,
  TextPosition? selectionExtent,
  int startAt = 1,
}) {
  final lineTexts = lines.isEmpty ? <String>[''] : List<String>.from(lines);
  final clampedCursor = _clampPositionToLines(cursor, lineTexts);
  final selection = selectionBase != null && selectionExtent != null
      ? TextSelection(base: selectionBase, extent: selectionExtent)
      : null;
  final hasSelection = selection != null && !selection.isCollapsed;
  final startLine = hasSelection ? selection.start.line : clampedCursor.line;
  final endLine = hasSelection ? selection.end.line : clampedCursor.line;
  final initialNumber = startAt < 1 ? 1 : startAt;

  var hasRelevantLine = false;
  var allNumbered = true;
  for (var lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
    final line = lineTexts[lineIndex];
    final leadingWhitespace = line.length - line.trimLeft().length;
    final body = line.substring(leadingWhitespace);
    if (body.trim().isEmpty) {
      continue;
    }
    hasRelevantLine = true;
    if (_leadingNumberedPrefixLength(body) == null) {
      allNumbered = false;
      break;
    }
  }

  var adjustedBase = selectionBase;
  var adjustedExtent = selectionExtent;
  var nextCursor = clampedCursor;
  var nextNumber = initialNumber;

  for (var lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
    final line = lineTexts[lineIndex];
    final leadingWhitespace = line.length - line.trimLeft().length;
    final indent = line.substring(0, leadingWhitespace);
    final body = line.substring(leadingWhitespace);
    final numberedPrefixLength = _leadingNumberedPrefixLength(body);
    final isBlank = body.trim().isEmpty;
    if (isBlank && hasRelevantLine) {
      continue;
    }

    final addPrefix = '${nextNumber++}. ';
    final removeCount = numberedPrefixLength ?? 0;
    final addCount = addPrefix.length;

    lineTexts[lineIndex] = allNumbered && removeCount > 0
        ? '$indent${body.substring(removeCount)}'
        : '$indent$addPrefix$body';

    if (!allNumbered) {
      if (lineIndex == nextCursor.line) {
        nextCursor = TextPosition(
          line: nextCursor.line,
          column: _adjustLinePrefixColumn(
            column: nextCursor.column,
            leadingWhitespace: leadingWhitespace,
            delta: addCount,
            remove: false,
          ),
        );
      }
      adjustedBase = _adjustLinePrefixPosition(
        adjustedBase,
        line: lineIndex,
        leadingWhitespace: leadingWhitespace,
        delta: addCount,
        remove: false,
      );
      adjustedExtent = _adjustLinePrefixPosition(
        adjustedExtent,
        line: lineIndex,
        leadingWhitespace: leadingWhitespace,
        delta: addCount,
        remove: false,
      );
      continue;
    }

    if (lineIndex == nextCursor.line) {
      nextCursor = TextPosition(
        line: nextCursor.line,
        column: _adjustLinePrefixColumn(
          column: nextCursor.column,
          leadingWhitespace: leadingWhitespace,
          delta: removeCount,
          remove: true,
        ),
      );
    }
    adjustedBase = _adjustLinePrefixPosition(
      adjustedBase,
      line: lineIndex,
      leadingWhitespace: leadingWhitespace,
      delta: removeCount,
      remove: true,
    );
    adjustedExtent = _adjustLinePrefixPosition(
      adjustedExtent,
      line: lineIndex,
      leadingWhitespace: leadingWhitespace,
      delta: removeCount,
      remove: true,
    );
  }

  if (_listStringEquals(lineTexts, lines)) {
    return _unchangedLineResult(
      lineTexts,
      cursor: clampedCursor,
      selectionBase: selectionBase,
      selectionExtent: selectionExtent,
    );
  }

  if (hasSelection && adjustedBase != null && adjustedExtent != null) {
    final clampedBase = _clampPositionToLines(adjustedBase, lineTexts);
    final clampedExtent = _clampPositionToLines(adjustedExtent, lineTexts);
    return TextLineCommandResult(
      lines: lineTexts,
      cursor: clampedExtent,
      selectionBase: clampedBase,
      selectionExtent: clampedExtent,
    );
  }

  return TextLineCommandResult(
    lines: lineTexts,
    cursor: _clampPositionToLines(nextCursor, lineTexts),
  );
}