toggleChecklistState function

TextLineCommandResult toggleChecklistState(
  1. List<String> lines, {
  2. required TextPosition cursor,
  3. TextPosition? selectionBase,
  4. TextPosition? selectionExtent,
  5. String checkedMarker = 'x',
})

Implementation

TextLineCommandResult toggleChecklistState(
  List<String> lines, {
  required TextPosition cursor,
  TextPosition? selectionBase,
  TextPosition? selectionExtent,
  String checkedMarker = 'x',
}) {
  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 marker = checkedMarker.isEmpty ? 'x' : checkedMarker[0];

  var hasChecklist = false;
  var allChecked = true;
  for (var lineIndex = startLine; lineIndex <= endLine; lineIndex++) {
    final line = lineTexts[lineIndex];
    final leadingWhitespace = line.length - line.trimLeft().length;
    final body = line.substring(leadingWhitespace);
    final prefixLength = _leadingChecklistPrefixLength(body);
    if (prefixLength == null) {
      continue;
    }
    hasChecklist = true;
    if (!_isChecklistChecked(body)) {
      allChecked = false;
      break;
    }
  }
  if (!hasChecklist) {
    return _unchangedLineResult(
      lineTexts,
      cursor: clampedCursor,
      selectionBase: selectionBase,
      selectionExtent: selectionExtent,
    );
  }

  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 prefixLength = _leadingChecklistPrefixLength(body);
    if (prefixLength == null) {
      continue;
    }

    final rest = body.substring(prefixLength);
    final hasBody = rest.isNotEmpty;
    final nextPrefix = allChecked ? '- [ ]' : '- [$marker]';
    lineTexts[lineIndex] = '$indent$nextPrefix${hasBody ? ' ' : ''}$rest';
  }

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

  return TextLineCommandResult(
    lines: lineTexts,
    cursor: _clampPositionToLines(clampedCursor, lineTexts),
    selectionBase: selectionBase == null
        ? null
        : _clampPositionToLines(selectionBase, lineTexts),
    selectionExtent: selectionExtent == null
        ? null
        : _clampPositionToLines(selectionExtent, lineTexts),
  );
}