sourcebuilder.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. const util = require('util');
  2. /**
  3. * This class should be used to build .py source files
  4. */
  5. class SourceBuilder {
  6. constructor(stream, indentSize) {
  7. this.currentIndent = 0;
  8. this.onNewLine = false;
  9. this.indentSize = indentSize || 4;
  10. this.stream = stream;
  11. // Was a new line added automatically before? If so, avoid it
  12. this.autoAddedLine = false;
  13. }
  14. /**
  15. * Indents the current source code line
  16. * by the current indentation level
  17. */
  18. indent() {
  19. this.write(' '.repeat(Math.abs(this.currentIndent * this.indentSize)));
  20. }
  21. /**
  22. * Writes a string into the source code,
  23. * applying indentation if required
  24. */
  25. write(string, ...args) {
  26. if (this.onNewLine) {
  27. this.onNewLine = false; // We're not on a new line anymore
  28. // If the string was not empty, indent; Else probably a new line
  29. if (string.trim()) {
  30. this.indent();
  31. }
  32. }
  33. if (args.length) {
  34. this.stream.write(util.format(string, ...args));
  35. } else {
  36. this.stream.write(string);
  37. }
  38. }
  39. /**
  40. * Writes a string into the source code _and_ appends a new line,
  41. * applying indentation if required
  42. */
  43. writeln(string, ...args) {
  44. this.write(`${string || ''}\n`, ...args);
  45. this.onNewLine = true;
  46. // If we're writing a block, increment indent for the next time
  47. if (string && string.endsWith('{')) {
  48. this.currentIndent++;
  49. }
  50. // Clear state after the user adds a new line
  51. this.autoAddedLine = false;
  52. }
  53. /**
  54. * Ends an indentation block, leaving an empty line afterwards
  55. */
  56. endBlock(semiColon = false) {
  57. this.currentIndent--;
  58. // If we did not add a new line automatically yet, now it's the time!
  59. if (!this.autoAddedLine) {
  60. this.writeln('}%s', semiColon ? ';' : '');
  61. this.autoAddedLine = true;
  62. }
  63. }
  64. }
  65. module.exports = SourceBuilder;