Last active
April 6, 2018 18:59
-
-
Save erica/fbf91d6742e2fd01cc3ee34561ee4c38 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cocoa | |
/// Processes text containing comment lines to fit them | |
/// within standard lldb 80-character width tolerance | |
/// | |
/// Code samples (indented by 4 spaces), non-doc comments, | |
/// and paragraph breaks are preserved. | |
/// | |
/// This does not yet handle keyword markup, such as for | |
/// `-Returns`, `-Parameter`, etc. | |
/// | |
/// - Parameter lines: An array of strings that represent | |
/// the contents of the source Swift file. | |
func processCommentLines(_ lines: [String]) { | |
/// Fit a blob of words into a standard lldb width | |
/// document comment template. | |
/// | |
/// - Parameter blob: A single-space delimited line of words. | |
/// - Parameter width: The wrapping width, set here to 78 characters. | |
/// - Returns: An ordered array of comment strings. | |
func formatCommentBlob(_ blob: String, width: Int = 78) -> [String] { | |
let words = blob | |
.components(separatedBy: .whitespaces) | |
.filter({ !$0.isEmpty }) | |
var line = "/// " | |
var lines: [String] = [] | |
for word in words { | |
// Handle very long word | |
if word.count > (width - 20) { | |
if line.count > 4 { | |
lines.append(line) | |
line = "/// " | |
} | |
lines.append("/// \(word)") | |
} | |
// Find room for this word | |
if line == "/// " { | |
line.append(word) // space is not added | |
} else if word.count + 1 + line.count < width { | |
line.append(" \(word)") | |
} else { // no room | |
lines.append(line) | |
line = "/// \(word)" | |
} | |
} | |
if line.count != 4 { | |
lines.append(line) | |
} | |
return lines | |
} | |
var lineIterator = lines.makeIterator() | |
var blob = "" | |
var (line, nextLine): (String?, String?) = (lineIterator.next(), lineIterator.next()) | |
let commentLinePrefix = "/// " | |
let codeBlockPrefix = "/// " | |
while true { | |
// Get a line | |
guard let aLine = line else { return } | |
let thisLine = aLine.trimmingCharacters(in: .whitespaces) | |
// Continue until comments | |
guard thisLine.hasPrefix(commentLinePrefix) else { | |
print(thisLine) | |
// Advance to the next line | |
(line, nextLine) = (nextLine, lineIterator.next()) | |
continue | |
} | |
// Preserve any code-indented line | |
guard !thisLine.hasPrefix(codeBlockPrefix) else { | |
print(thisLine) | |
// Advance to the next line | |
(line, nextLine) = (nextLine, lineIterator.next()) | |
continue | |
} | |
// Fetch until code, non-comment, or para break | |
blob = "" | |
while let thisLine = line { | |
// Increase the blob. Trimmed lines have no spaces | |
// so the offset is only 3. | |
let idx = thisLine.index(thisLine.startIndex, offsetBy: 3) | |
blob += thisLine[idx...] | |
// Is it time to finish the blob? | |
if let nextLine = nextLine, | |
nextLine.hasPrefix(codeBlockPrefix) | |
|| !nextLine.hasPrefix(commentLinePrefix) | |
|| nextLine == "///" { | |
// there is a next line and it does not belong to this blob | |
break | |
} | |
// Advance to the next line | |
(line, nextLine) = (nextLine, lineIterator.next()) | |
} | |
// Output blob line by line to stdout | |
formatCommentBlob(blob).forEach { print($0)} | |
// Advance to the next line | |
(line, nextLine) = (nextLine, lineIterator.next()) | |
} | |
} | |
let sourceFile = #fileLiteral(resourceName: "test.swift") | |
let contents = try! NSString(contentsOf: sourceFile, encoding: String.Encoding.utf8.rawValue) | |
let lines = contents.components(separatedBy: "\n") | |
processCommentLines(lines) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment