const util = require('util') /** * This class should be used to build .py source files */ class SourceBuilder { constructor(stream, indentSize) { this.currentIndent = 0 this.onNewLine = false this.indentSize = indentSize || 4 this.stream = stream // Was a new line added automatically before? If so, avoid it this.autoAddedLine = false } /** * Indents the current source code line * by the current indentation level */ indent() { this.write(' '.repeat(Math.abs(this.currentIndent * this.indentSize))) } /** * Writes a string into the source code, * applying indentation if required */ write(string, ...args) { if (this.onNewLine) { this.onNewLine = false // We're not on a new line anymore // If the string was not empty, indent; Else probably a new line if (string.trim()) { this.indent() } } if (args.length) { this.stream.write(util.format(string, ...args)) } else { this.stream.write(string) } } /** * Writes a string into the source code _and_ appends a new line, * applying indentation if required */ writeln(string, ...args) { this.write(`${string || ''}\n`, ...args) this.onNewLine = true // If we're writing a block, increment indent for the next time if (string && string.endsWith('{')) { this.currentIndent++ } // Clear state after the user adds a new line this.autoAddedLine = false } /** * Ends an indentation block, leaving an empty line afterwards */ endBlock(semiColon = false) { this.currentIndent-- // If we did not add a new line automatically yet, now it's the time! if (!this.autoAddedLine) { this.writeln('}%s', semiColon ? ';' : '') this.autoAddedLine = true } } } module.exports = SourceBuilder