david-swift 4de2d312ab
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
Fix style
2025-11-05 13:04:53 +01:00

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
}
}