CodePrinter.swift 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Sources/SwiftProtobufPluginLibrary/CodePrinter.swift - Code output
  2. //
  3. // Copyright (c) 2014 - 2016 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. ///
  11. /// This provides some basic indentation management for emitting structured
  12. /// source code text.
  13. ///
  14. // -----------------------------------------------------------------------------
  15. /// Prints code with automatic indentation based on calls to `indent` and
  16. /// `outdent`.
  17. public struct CodePrinter {
  18. /// Reserve an initial buffer of 64KB scalars to eliminate some reallocations
  19. /// in smaller files.
  20. private static let initialBufferSize = 65536
  21. /// The string content that was printed.
  22. public var content: String {
  23. return String(contentScalars)
  24. }
  25. /// See if anything was printed.
  26. public var isEmpty: Bool { return content.isEmpty }
  27. /// The Unicode scalar buffer used to build up the printed contents.
  28. private var contentScalars = String.UnicodeScalarView()
  29. /// The `UnicodeScalarView` representing a single indentation step.
  30. private let singleIndent: String.UnicodeScalarView
  31. /// The current indentation level (a collection of spaces).
  32. private var indentation = String.UnicodeScalarView()
  33. /// Keeps track of whether the printer is currently sitting at the beginning
  34. /// of a line.
  35. private var atLineStart = true
  36. public init(indent: String.UnicodeScalarView = " ".unicodeScalars) {
  37. contentScalars.reserveCapacity(CodePrinter.initialBufferSize)
  38. singleIndent = indent
  39. }
  40. /// Writes the given strings to the printer.
  41. ///
  42. /// - Parameter text: A variable-length list of strings to be printed.
  43. public mutating func print(_ text: String...) {
  44. for t in text {
  45. for scalar in t.unicodeScalars {
  46. // Indent at the start of a new line, unless it's a blank line.
  47. if atLineStart && scalar != "\n" {
  48. contentScalars.append(contentsOf: indentation)
  49. }
  50. contentScalars.append(scalar)
  51. atLineStart = (scalar == "\n")
  52. }
  53. }
  54. }
  55. /// Increases the printer's indentation level.
  56. public mutating func indent() {
  57. indentation.append(contentsOf: singleIndent)
  58. }
  59. /// Decreases the printer's indentation level.
  60. ///
  61. /// - Precondition: The printer must not have an indentation level.
  62. public mutating func outdent() {
  63. let indentCount = singleIndent.count
  64. precondition(indentation.count >= indentCount, "Cannot outdent past the left margin")
  65. indentation.removeLast(indentCount)
  66. }
  67. }