Contents

openswiftuiproject/swift-sexp

swift-sexp is a lightweight utility for building [S-expression](https://en.wikipedia.org/wiki/S-expression) formatted output strings in Swift, plus a small toolkit of protocols for rendering recursive descriptions of Swift types.

Overview

swift-sexp is a cross-platform Swift package on Darwin platform and Linux. Requires Swift 6.1+ (tools version 6.1).

| Workflow | CI Status | |-|:-| | macOS Unit Test | [[macOS]](https://github.com/OpenSwiftUIProject/swift-sexp/actions/workflows/macos.yml) | | Ubuntu 22.04 Unit Test | [[Ubuntu]](https://github.com/OpenSwiftUIProject/swift-sexp/actions/workflows/ubuntu.yml) |

The package exposes two library products:

SExpPrinter

  • SExpPrinter — A value type that incrementally builds S-expression output with proper nesting and indentation.
  • SExpPrintable — A protocol that conforming types can adopt to provide S-expression descriptions via CustomStringConvertible.
public protocol SExpPrintable: CustomStringConvertible {
    var tag: String { get }
    func print(into printer: inout SExpPrinter)
}

SwiftDescription

  • CustomRecursiveStringConvertible — A protocol that produces a hierarchical XML-style description of a type's attributes and children. Companion enum DefaultDescriptionAttribute names common graphical attributes.
  • NestedCustomStringConvertible — A protocol that produces a nested, brace-indented description using Mirror by default, with hooks for custom prefixes/suffixes.

Enable the package trait OpenSwiftUI to activate an extra Color.Resolved.name extension backed by OpenSwiftUICore. On Apple platforms with SwiftUI 7.0+ (iOS/macOS 26+) the same extension is offered on Color.ResolvedHDR.

Getting Started

In your Package.swift file, add the following dependency to your dependencies argument:

.package(url: "https://github.com/OpenSwiftUIProject/swift-sexp.git", from: "0.1.0"),

Then add the dependency to any targets you've declared in your manifest:

.target(
    name: "MyTarget",
    dependencies: [
        .product(name: "SExpPrinter", package: "swift-sexp"),
        .product(name: "SwiftDescription", package: "swift-sexp"),
    ]
),

Example

import SExpPrinter

var printer = SExpPrinter(tag: "root")
printer.push("child")
printer.print("value")
printer.pop()
let output = printer.end()
// (root
//   (child
//     value))

Conform your types to SExpPrintable for automatic description:

struct MyNode: SExpPrintable {
    var tag: String { "MyNode" }
    func print(into printer: inout SExpPrinter) {
        printer.print("key=value")
    }
}

print(MyNode()) // (MyNode key=value)

Maintenance

Vendored sources (SExpPrinter + SwiftDescription) are synced from OpenSwiftUI and OpenGestures. The mapping and last-synced commits are tracked in UPSTREAM.md. The re-sync procedure is described in CLAUDE.md (symlinked as AGENT.md for Codex) — running it is a one-prompt operation for any LLM agent.

License

See LICENSE file - MIT

Package Metadata

Repository: openswiftuiproject/swift-sexp

Default branch: main

README: README.md