Created
May 15, 2022 01:30
-
-
Save matanlurey/6e45a265f743513ac4d3688c2d87826e to your computer and use it in GitHub Desktop.
A fairly simple way to enhance "StringBuffer" to make recursive indentation easier.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension IdentableStringSink on StringSink { | |
/// Provides a delegating implementation of [StringSink] on [invoke]. | |
/// | |
/// ``` | |
/// String example(String name, int age) { | |
/// final sink = StringBuffer(); | |
/// sink | |
/// ..writeln('Identification') | |
/// ..indent(2, (sink) { | |
/// sink | |
/// ..writeln('name: $name') | |
/// ..writeln('age: $age'); | |
/// }); | |
/// // Identification: | |
/// // name: $name | |
/// // age: $age | |
/// return sink.toString(); | |
/// } | |
/// ``` | |
/// | |
/// **IMPORTANT**: Indentation is _recursive_ when it's invoked on itself: | |
/// | |
/// ``` | |
/// String double(String c) { | |
/// final sink = StringBuffer(); | |
/// sink | |
/// ..writeln('a:') | |
/// ..indent(2, (sink) { | |
/// sink | |
/// ..writeln('b: ) | |
/// ..writeIndented(2, 'c: $c'); | |
/// }); | |
/// // a: | |
/// // b: | |
/// // c: $c | |
/// return sink.toString(); | |
/// } | |
/// ``` | |
/// | |
/// ... so, **do not** store the sink provided to [invoke]. | |
void indent(int amount, void Function(/* @doNotStore */ StringSink) invoke) { | |
final self = this; | |
if (self is _PrefixedStringSink) { | |
final prefix = '${self._prefix}${' ' * amount}'; | |
final delegate = _PrefixedStringSink(self._sink, prefix); | |
invoke(delegate); | |
} else { | |
invoke(_PrefixedStringSink(self, ' ' * amount)); | |
} | |
} | |
/// A helper function for invoking [indent] with a single [immediate]. | |
void writeIntended(int amount, String immediate) { | |
indent(2, (sink) => sink.write(immediate)); | |
} | |
/// A helper function for invoking [indent] with a single [immediate]. | |
void writelnIntended(int amount, String immediate) { | |
indent(2, (sink) => sink.writeln(immediate)); | |
} | |
} | |
class _PrefixedStringSink implements StringSink { | |
final StringSink _sink; | |
final String _prefix; | |
_PrefixedStringSink(this._sink, this._prefix); | |
@override | |
void write(Object? object) { | |
_sink | |
..write(_prefix) | |
..write(object); | |
} | |
@override | |
void writeAll(Iterable<Object?> objects, [String separator = '']) { | |
_sink.writeAll(objects.map((e) => '$_prefix$e'), separator); | |
} | |
@override | |
void writeCharCode(int charCode) { | |
_sink | |
..write(_prefix) | |
..writeCharCode(charCode); | |
} | |
@override | |
void writeln([Object? object = '']) { | |
_sink | |
..write(_prefix) | |
..writeln(object); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment