123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- export class StringAccumulator {
- lines: Line[];
- constructor() {
- this.lines = [new Line()];
- }
- get lastLine(): Line {
- return this.lines.at(-1) as Line;
- }
- add(token: string) {
- if (!token) {
- return;
- }
- this.lastLine.add(token);
- }
- space() {
- this.lastLine.add(SPACE);
- }
- break() {
- const newLine = new Line();
- newLine.indentTo(this.lastLine.indentation);
- this.lines.push(newLine);
- }
- indent() {
- this.lastLine.indent();
- }
- unindent() {
- this.lastLine.unindent();
- }
- indentTo(level: number = 1) {
- this.lastLine.indentTo(level);
- }
- toString(maxLineLength: number = DEFAULT_MAX_LINE_LENGTH) {
- let output: Line[] = [];
- this.lines.forEach(line => {
- if (line.textLength <= maxLineLength) {
- output.push(line);
- return;
- }
- const splitLines: Line[] = [new Line([], line.indentation)];
- let tokenIndex = 0;
- while (tokenIndex < line.tokens.length) {
- const incomingToken = line.tokens.at(tokenIndex) as string;
- const totalLength = (splitLines.at(-1) as Line).textLength + incomingToken.length;
- if (totalLength <= maxLineLength) {
- splitLines.at(-1)?.add(incomingToken);
- } else {
- splitLines.push(new Line([incomingToken], line.indentation + 1));
- }
- tokenIndex += 1;
- }
- output = [...output, ...splitLines.filter(splitLine => !splitLine.isEmpty)];
- });
- return output.join(NEWLINE).trim();
- }
- }
- const DEFAULT_MAX_LINE_LENGTH = 100;
- class Line {
- tokens: string[];
- indentation: number;
- constructor(tokens: string[] = [], indentation: number = 0) {
- this.tokens = tokens;
- this.indentation = indentation;
- }
- get isEmpty() {
- return this.toString().trim() === '';
- }
- get length() {
- return this.toString().length;
- }
- get textLength() {
- return this.toString().trim().length;
- }
- add(token: string) {
- this.tokens.push(token);
- }
- indent() {
- this.indentation += 1;
- }
- unindent() {
- this.indentation -= 1;
- }
- indentTo(level: number) {
- this.indentation = level;
- }
- toString() {
- return `${INDENTATION.repeat(this.indentation)}${this.tokens.join('').trimEnd()}`;
- }
- }
- const SPACE = ' ';
- const INDENTATION = ' ';
- const NEWLINE = '\n';
|