codeToggleBlockComments function
TextCommandResult
codeToggleBlockComments({
- required TextDocument document,
- required TextOffsetStateSnapshot state,
- required CodeLanguageProfile profile,
Implementation
TextCommandResult codeToggleBlockComments({
required TextDocument document,
required TextOffsetStateSnapshot state,
required CodeLanguageProfile profile,
}) {
final delimiters = profile.blockCommentDelimiters;
if (delimiters == null || document.length == 0) {
return _unchangedCodeResultFromDocument(document, state);
}
final selection = normalizedSelectionRange(
state.selectionBaseOffset,
state.selectionExtentOffset,
);
final hasSelection = selection != null && selection.start != selection.end;
final cursor = document.positionForOffset(state.cursorOffset);
final line = cursor.line.clamp(0, document.lineCount - 1);
final start = hasSelection
? selection.start
: document.offsetForPosition(TextPosition(line: line, column: 0));
final end = hasSelection
? selection.end
: document.offsetForPosition(
TextPosition(line: line, column: document.lineLength(line)),
);
if (start >= end) {
return _unchangedCodeResultFromDocument(document, state);
}
final clampedStart = start < 0
? 0
: (start > document.length ? document.length : start);
final clampedEnd = end < clampedStart
? clampedStart
: (end > document.length ? document.length : end);
if (clampedStart >= clampedEnd) {
return _unchangedCodeResultFromDocument(document, state);
}
final startGraphemes = delimiters.start.characters.toList(growable: false);
final endGraphemes = delimiters.end.characters.toList(growable: false);
final segment = document.graphemesInRange(
startOffset: clampedStart,
endOffset: clampedEnd,
);
final leadingWhitespace = _leadingWhitespaceCount(segment);
final trailingWhitespace = _trailingWhitespaceCount(segment);
final coreEnd = segment.length - trailingWhitespace;
final core = segment.sublist(leadingWhitespace, coreEnd);
List<String> replacement;
var selectionStart = leadingWhitespace;
late int selectionEnd;
if (_startsWithGraphemeSequence(core, startGraphemes) &&
_endsWithGraphemeSequence(core, endGraphemes)) {
var innerStart = leadingWhitespace + startGraphemes.length;
var innerEnd = coreEnd - endGraphemes.length;
if (innerStart < innerEnd && segment[innerStart] == ' ') {
innerStart++;
}
if (innerStart < innerEnd && segment[innerEnd - 1] == ' ') {
innerEnd--;
}
replacement = <String>[
...segment.sublist(0, leadingWhitespace),
...segment.sublist(innerStart, innerEnd),
...segment.sublist(coreEnd),
];
selectionEnd = selectionStart + (innerEnd - innerStart);
} else {
final separator = core.isEmpty ? const <String>[] : const <String>[' '];
replacement = <String>[
...segment.sublist(0, leadingWhitespace),
...startGraphemes,
...separator,
...core,
...separator,
...endGraphemes,
...segment.sublist(coreEnd),
];
selectionEnd =
selectionStart +
startGraphemes.length +
separator.length +
core.length +
separator.length +
endGraphemes.length;
}
if (_listStringEquals(replacement, segment)) {
return _unchangedCodeResultFromDocument(document, state);
}
final working = document.copy();
final result = edit_ops.replaceDocumentTextRange(
working,
start: clampedStart,
end: clampedEnd,
replacement: replacement.join(),
);
final nextSelectionStart = clampedStart + selectionStart;
final nextSelectionEnd = clampedStart + selectionEnd;
if (hasSelection) {
return _codeResultFromDocument(
working,
cursorOffset: nextSelectionEnd,
selectionBaseOffset: nextSelectionStart,
selectionExtentOffset: nextSelectionEnd,
documentChange: result.change,
changed: result.changed,
);
}
return _codeResultFromDocument(
working,
cursorOffset: nextSelectionEnd,
documentChange: result.change,
changed: result.changed,
);
}