diff --git a/Sources/CliDoc/Nodes/AnyNode.swift b/Sources/CliDoc/Nodes/AnyNode.swift index ece711d..f20132f 100644 --- a/Sources/CliDoc/Nodes/AnyNode.swift +++ b/Sources/CliDoc/Nodes/AnyNode.swift @@ -1,21 +1,34 @@ +// TODO: This doesn't seem correct, maybe remove this type. public struct AnyNode: NodeRepresentable { + @usableFromInline - let node: any NodeRepresentable + let makeBody: @Sendable () -> String + +// @usableFromInline +// let node: Value @inlinable public init(@NodeBuilder _ build: () -> N) { - self.node = build() + self.makeBody = build().render } @inlinable public init(_ node: N) { - self.node = node + self.makeBody = node.render } - @inlinable public func render() -> String { - node.render() + makeBody() } +// +// public var body: some NodeRepresentable { +// node +// } + +// @inlinable +// public func render() -> String { +// node.render() +// } } public extension NodeRepresentable { diff --git a/Sources/CliDoc/Nodes/Group.swift b/Sources/CliDoc/Nodes/Group.swift index 3af1320..a15aeaa 100644 --- a/Sources/CliDoc/Nodes/Group.swift +++ b/Sources/CliDoc/Nodes/Group.swift @@ -2,36 +2,62 @@ public struct Group: NodeRepresentable { @usableFromInline let node: any NodeRepresentable - @usableFromInline - init( - separator: AnyNode, - node: any NodeRepresentable + @inlinable + public init( + separator: any NodeRepresentable = " ", + @NodeBuilder node: () -> any NodeRepresentable ) { if let many = node as? _ManyNode { self.node = _ManyNode(many.nodes, separator: separator) } else { - self.node = node + self.node = node() } } - @inlinable - public init( - separator: any NodeRepresentable, - @NodeBuilder _ build: () -> any NodeRepresentable - ) { - self.init(separator: separator.eraseToAnyNode(), node: build()) - } +// @inlinable +// public init( +// separator: any NodeRepresentable, +// @NodeBuilder _ build: () -> any NodeRepresentable +// ) { +// self.init(separator: separator.eraseToAnyNode(), node: build()) +// } - @inlinable - public init( - separator: String = " ", - @NodeBuilder _ build: () -> any NodeRepresentable - ) { - self.init(separator: separator.eraseToAnyNode(), node: build()) - } +// @inlinable +// public init( +// separator: String = " ", +// @NodeBuilder _ build: () -> any NodeRepresentable +// ) { +// self.init(separator: separator.eraseToAnyNode(), node: build()) +// } @inlinable public func render() -> String { node.render() } } + +public struct Group2: Node { + + @usableFromInline + let content: Content + + @usableFromInline + let separator: any NodeRepresentable + + @inlinable + public init( + separator: any NodeRepresentable = " ", + @NodeBuilder _ content: () -> Content + ) { + self.content = content() + self.separator = separator + } + + @inlinable + public var body: some NodeRepresentable { + guard let content = content as? _ManyNode else { + return content.eraseToAnyNode() + } + return _ManyNode(content.nodes, separator: separator).eraseToAnyNode() + } +} diff --git a/Sources/CliDoc/Nodes/LabeledContent.swift b/Sources/CliDoc/Nodes/LabeledContent.swift index da55109..289abb2 100644 --- a/Sources/CliDoc/Nodes/LabeledContent.swift +++ b/Sources/CliDoc/Nodes/LabeledContent.swift @@ -44,3 +44,32 @@ public extension LabeledContent { } } } + +public struct LabeledContent2: Node { + + @usableFromInline + let separator: any NodeRepresentable + + @usableFromInline + let label: Label + + @usableFromInline + let content: Content + + public init( + separator: any NodeRepresentable = " ", + @NodeBuilder label: () -> Label, + @NodeBuilder content: () -> Content + ) { + self.separator = separator + self.label = label() + self.content = content() + } + + public var body: some NodeRepresentable { + Group2(separator: separator) { + label + content + } + } +} diff --git a/Sources/CliDoc/Nodes/String+NodeRepresentable.swift b/Sources/CliDoc/Nodes/String+NodeRepresentable.swift index 49c61a3..139d280 100644 --- a/Sources/CliDoc/Nodes/String+NodeRepresentable.swift +++ b/Sources/CliDoc/Nodes/String+NodeRepresentable.swift @@ -4,3 +4,10 @@ extension String: NodeRepresentable { self } } + +extension String: Node { + + public var body: some NodeRepresentable { + self + } +} diff --git a/Sources/CliDoc/Nodes/Text.swift b/Sources/CliDoc/Nodes/Text.swift index a2f8212..8ea863c 100644 --- a/Sources/CliDoc/Nodes/Text.swift +++ b/Sources/CliDoc/Nodes/Text.swift @@ -1,6 +1,6 @@ @preconcurrency import Rainbow -public struct Text: NodeRepresentable { +public struct Text: Node { @usableFromInline let text: String @@ -10,7 +10,7 @@ public struct Text: NodeRepresentable { } @inlinable - public func render() -> String { + public var body: some NodeRepresentable { text } } diff --git a/Tests/CliDocTests/CliDocTests.swift b/Tests/CliDocTests/CliDocTests.swift index 0137e0a..2dc2221 100644 --- a/Tests/CliDocTests/CliDocTests.swift +++ b/Tests/CliDocTests/CliDocTests.swift @@ -96,6 +96,23 @@ final class CliDocTests: XCTestCase { XCTAssert(node.render() == expected) } + func testLabeledContent2() { + let node = LabeledContent2 { + "Foo" + } content: { + Text("Bar") + } +// .labelStyle(.green) +// .labelStyle(.bold) + + let expected = """ + Foo Bar + """ + XCTAssert(node.render() == expected) + print(type(of: node.body)) + XCTAssertNotNil(node.body as? _ManyNode) + } + func testShellCommand() { let node = ShellCommand { "ls -lah" @@ -126,4 +143,14 @@ final class CliDocTests: XCTestCase { let foo = Foo() XCTAssertNotNil(foo.body as? LabeledContent) } + + func testGroup2() { + let node = Group2 { + Text("foo") + Text("bar") + } + print(node.render()) + XCTAssertNotNil(node.body as? _ManyNode) + // XCTAssert(false) + } }