mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:41:19 +00:00
cf3387efd3
Change-Id: Iabd0edb24eee278c3f12a9f61fe535645e1f26d6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/208761 Commit-Queue: Riley Porter <rileyporter@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
134 lines
3.5 KiB
Dart
134 lines
3.5 KiB
Dart
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
/// Indentation utility class. Should be used as a mixin in most cases.
|
|
class Indentation {
|
|
/// The current indentation string.
|
|
String get indentation {
|
|
// Lazily add new indentation strings as required.
|
|
for (int i = _indentList.length; i <= _indentLevel; i++) {
|
|
_indentList.add(_indentList[i - 1] + indentationUnit);
|
|
}
|
|
return _indentList[_indentLevel];
|
|
}
|
|
|
|
/// The current indentation level.
|
|
int _indentLevel = 0;
|
|
|
|
/// A cache of all indentation strings used so far.
|
|
/// Always at least of length 1.
|
|
List<String> _indentList = <String>[""];
|
|
|
|
/// The indentation unit, defaulting to two spaces. May be overwritten.
|
|
String _indentationUnit = " ";
|
|
String get indentationUnit => _indentationUnit;
|
|
set indentationUnit(String value) {
|
|
if (value != _indentationUnit) {
|
|
_indentationUnit = value;
|
|
_indentList = <String>[""];
|
|
}
|
|
}
|
|
|
|
/// Increases the current level of indentation.
|
|
void indentMore() {
|
|
_indentLevel++;
|
|
}
|
|
|
|
/// Decreases the current level of indentation.
|
|
void indentLess() {
|
|
_indentLevel--;
|
|
}
|
|
|
|
/// Calls [f] with one more indentation level, restoring indentation context
|
|
/// upon return of [f] and returning its result.
|
|
indentBlock(Function f) {
|
|
indentMore();
|
|
dynamic result = f();
|
|
indentLess();
|
|
return result;
|
|
}
|
|
}
|
|
|
|
abstract class Tagging<N> implements Indentation {
|
|
StringBuffer sb = new StringBuffer();
|
|
List<String> tagStack = [];
|
|
|
|
void pushTag(String tag) {
|
|
tagStack.add(tag);
|
|
indentMore();
|
|
}
|
|
|
|
String popTag() {
|
|
assert(!tagStack.isEmpty);
|
|
indentLess();
|
|
return tagStack.removeLast();
|
|
}
|
|
|
|
/// Adds given string to result string.
|
|
void add(String string) {
|
|
sb.write(string);
|
|
}
|
|
|
|
/// Adds default parameters for [node] into [params].
|
|
void addDefaultParameters(N node, Map params) {}
|
|
|
|
/// Adds given node type to result string.
|
|
/// The method "opens" the node, meaning that all output after calling
|
|
/// this method and before calling closeNode() will represent contents
|
|
/// of given node.
|
|
void openNode(N node, String type, [Map? params]) {
|
|
if (params == null) params = new Map();
|
|
addCurrentIndent();
|
|
sb.write("<");
|
|
addDefaultParameters(node, params);
|
|
addTypeWithParams(type, params);
|
|
sb.write(">\n");
|
|
pushTag(type);
|
|
}
|
|
|
|
/// Adds given node to result string.
|
|
void openAndCloseNode(N node, String type, [Map? params]) {
|
|
if (params == null) params = {};
|
|
addCurrentIndent();
|
|
sb.write("<");
|
|
addDefaultParameters(node, params);
|
|
addTypeWithParams(type, params);
|
|
sb.write("/>\n");
|
|
}
|
|
|
|
/// Closes current node type.
|
|
void closeNode() {
|
|
String tag = popTag();
|
|
addCurrentIndent();
|
|
sb.write("</");
|
|
addTypeWithParams(tag);
|
|
sb.write(">\n");
|
|
}
|
|
|
|
void addTypeWithParams(String type, [Map? params]) {
|
|
if (params == null) params = new Map();
|
|
sb.write("${type}");
|
|
params.forEach((k, v) {
|
|
String value;
|
|
if (v != null) {
|
|
String str = valueToString(v);
|
|
value = str
|
|
.replaceAll("<", "<")
|
|
.replaceAll(">", ">")
|
|
.replaceAll('"', "'");
|
|
} else {
|
|
value = "[null]";
|
|
}
|
|
sb.write(' $k="$value"');
|
|
});
|
|
}
|
|
|
|
void addCurrentIndent() {
|
|
sb.write(indentation);
|
|
}
|
|
|
|
/// Converts a parameter value into a string.
|
|
String valueToString(dynamic value) => value;
|
|
}
|