164 lines
5.9 KiB
Swift
164 lines
5.9 KiB
Swift
//
|
|
// String.swift
|
|
// Adwaita
|
|
//
|
|
// Created by david-swift on 14.01.24.
|
|
//
|
|
|
|
extension String: @retroactive CodingKey {
|
|
|
|
/// The string.
|
|
public var stringValue: String {
|
|
self
|
|
}
|
|
|
|
/// A string cannot be represented as an integer.
|
|
public var intValue: Int? {
|
|
nil
|
|
}
|
|
|
|
/// Initialize from an int value.
|
|
/// - Parameter intValue: The int value.
|
|
public init?(intValue: Int) {
|
|
nil
|
|
}
|
|
|
|
/// Initialize from a string value.
|
|
/// - Parameter stringValue: The string value.
|
|
public init?(stringValue: String) {
|
|
self = stringValue
|
|
}
|
|
|
|
/// Generate a doc comment out of the string.
|
|
/// - Parameters:
|
|
/// - configuration: The generation configuration.
|
|
/// - indent: Indentation added at the beginning of every line.
|
|
/// - Returns: The comment.
|
|
func docComment(configuration: GenerationConfiguration, indent: String = "") -> String {
|
|
applyDocRegex(configuration: configuration)
|
|
.split(separator: "\n", omittingEmptySubsequences: false)
|
|
.map { $0.trimmingCharacters(in: .whitespaces) }
|
|
.enumerated()
|
|
.map { $0.offset == 0 ? $0.element.prefix(1).capitalized + $0.element.dropFirst() : $0.element }
|
|
.map { "\(indent)/// \($0)" }
|
|
.joined(separator: "\n")
|
|
}
|
|
|
|
/// Convert delimited to camel casing.
|
|
/// - Parameters:
|
|
/// - delimiter: The demiliter.
|
|
/// - unshorten: Whether to unshorten.
|
|
/// - configuration: The generation configuration.
|
|
/// - Returns: The string using camel casing.
|
|
func convertDelimitedCasingToCamel(
|
|
delimiter: Character,
|
|
configuration: GenerationConfiguration,
|
|
unshorten: Bool = false
|
|
) -> String {
|
|
var parts = split(separator: delimiter).map(String.init)
|
|
for (index, part) in parts.enumerated() {
|
|
if let replacement = configuration.unshorteningMap[part] {
|
|
parts[index] = replacement
|
|
}
|
|
}
|
|
let first = parts.removeFirst()
|
|
return first + parts.map(\.capitalized).joined()
|
|
}
|
|
|
|
/// Convert a C type to its Swift equivalent using the generation configuration.
|
|
/// - Parameter configuration: The generation configuration.
|
|
/// - Returns: The Swift type.
|
|
func convertCType(configuration: GenerationConfiguration) -> String {
|
|
if let replacement = configuration.cTypeReplacements[self] {
|
|
return replacement
|
|
}
|
|
var type = self
|
|
if type.last == "*" {
|
|
let pointeeType = String(type.dropLast()).convertCType(configuration: configuration)
|
|
type = "UnsafeMutablePointer<\(pointeeType)>!"
|
|
}
|
|
return type
|
|
}
|
|
|
|
/// Apply the documentation regex.
|
|
/// - Parameter configuration: The generation configuration.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applyDocRegex(configuration: GenerationConfiguration) -> String {
|
|
var modified = self
|
|
do {
|
|
modified = try modified.applyExtraContentRegex()
|
|
modified = try modified.applySimpleRegex()
|
|
modified = try modified.applyPropertyRegex(configuration: configuration)
|
|
modified = try modified.applyBooleanRegex()
|
|
modified = try modified.applyHTMLRegex()
|
|
modified = try modified.applyNoteRegex()
|
|
return modified
|
|
} catch {
|
|
print("FAIL!")
|
|
return modified
|
|
}
|
|
}
|
|
|
|
/// Apply the regex to remove additional documentation content.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applyExtraContentRegex() throws -> String {
|
|
let extraContent = try Regex("##?(.|\\n)*")
|
|
return replacing(extraContent, with: "")
|
|
}
|
|
|
|
/// Translate simple definitions into Markdown inline code.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applySimpleRegex() throws -> String {
|
|
let regex = try Regex("\\[(class|func|method|ctor|signal|const|iface)@(.*?)\\]")
|
|
return replacing(regex) { match in
|
|
"`\(match.output[2].substring ?? "")`"
|
|
}
|
|
}
|
|
|
|
/// Translate property definitions into Swift references.
|
|
/// - Parameter configuration: The generation configuration.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applyPropertyRegex(configuration: GenerationConfiguration) throws -> String {
|
|
let property = try Regex("\\[property@(.*?)\\:(.*?)\\]")
|
|
return replacing(property) { match in
|
|
let method = String(match.output[2].substring ?? "")
|
|
.convertDelimitedCasingToCamel(delimiter: "-", configuration: configuration, unshorten: true)
|
|
return "``\(method)(_:)``"
|
|
}
|
|
}
|
|
|
|
/// Translate booleans into inline Markdown code with Swift booleans.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applyBooleanRegex() throws -> String {
|
|
var modified = self
|
|
let `false` = try Regex("(`|%)FALSE`?")
|
|
modified = modified.replacing(`false`, with: "`false`")
|
|
let `true` = try Regex("(`|%)TRUE`?")
|
|
modified = modified.replacing(`true`, with: "`true`")
|
|
return modified
|
|
}
|
|
|
|
/// Remove broken HTML tags.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applyHTMLRegex() throws -> String {
|
|
let picture = try Regex("<picture>.*?</picture>")
|
|
return replacing(picture, with: "")
|
|
}
|
|
|
|
/// Interpret note/warning blocks.
|
|
/// - Returns: The documentation with the regex applied.
|
|
func applyNoteRegex() throws -> String {
|
|
var modified = self
|
|
let note = try Regex("::: note\\n((.|\\n)*?)(\\n\\n)?")
|
|
modified = modified.replacing(note) { match in
|
|
"> [!NOTE]\n> \(match.output[1].substring ?? "")"
|
|
}
|
|
let warning = try Regex("::: warning\\n((.|\\n)*?)(\\n\\n)?")
|
|
modified = modified.replacing(warning) { match in
|
|
"> [!WARNING]\n> \(match.output[1].substring ?? "")"
|
|
}
|
|
return modified
|
|
}
|
|
|
|
}
|