import { BlockPair } from '../plugin'; const MAX_STACK_LENGTH = 20; export class SpecScriptPrinter { constructor(protected printer: ScriptPrinter) {} private _func(funcName: string): void { this.printer.echo(`function ${funcName}() `); this.printer.push(); } private _comment(comments: string): void { const lines = comments.split('\n'); lines.forEach((line, i) => { if (i === 0) { this.printer.echo('/** \n'); } this.printer.echo(' * ' + line + '\n'); if (i === lines.length - 1) { this.printer.echo(' */\n'); } }); } func = this._func.bind(this); comment = this._comment.bind(this); } export class ScriptPrinter { private _newLine: boolean = true; private _depth: number = 0; private _output: string = ''; private _stacks: string[] = []; private _blocks: BlockPair[] = []; get output(): string { return this._output; } echo(value: string): void { if (!value) { return; } const text = (this._newLine ? Array(this._depth * 2) .fill(' ') .join('') : '') + value; if (this._stacks.length === MAX_STACK_LENGTH) { this._stacks.splice(0, 1); } this._stacks.push(text); this._output += text; const trimSpace = this._output.replace(/ +?/g, ''); if (trimSpace[trimSpace.length - 1] === '\n' || this._output === '') { this._newLine = true; } else { this._newLine = false; } } undo(): void { const stack = this._stacks.pop(); if (!stack) { return; } this._output = this._output.substring( 0, this._output.length - stack.length ); if ( this._output.length === 0 || this._output[this._output.length - 1] === '\n' ) { this._newLine = true; } } private _getPair(type: BlockPair): string[] { switch (type) { case BlockPair.braces: return ['{', '}']; case BlockPair.bracket: return ['[', ']']; case BlockPair.Parentheses: return ['(', ')']; case BlockPair.Space: return ['', '']; default: throw new Error('Not supported block pair!'); } } push(type: BlockPair = BlockPair.braces, newLine: boolean = true): void { const pair = this._getPair(type); this.echo(`${pair[0]}${newLine ? '\n' : ''}`); this._blocks.push(type); this._depth = this._blocks.length; this._stacks = []; } pop(newLine: boolean = true): void { const type = this._blocks.pop(); if (!type) { return; } const pair = this._getPair(type); this._depth = this._blocks.length; this.echo(`${pair[1]}${newLine ? '\n' : ''}`); this._stacks = []; } flush(): string { const output = this._output; this._output = ''; this._stacks = []; return output; } }