feat: Working on documentation
All checks were successful
CI / Run tests. (push) Successful in 58s

This commit is contained in:
2024-12-09 09:35:17 -05:00
parent 78a632c3e5
commit 875b1980e0
9 changed files with 100 additions and 8 deletions

26
Examples/README.md Normal file
View File

@@ -0,0 +1,26 @@
# swift-cli-doc
A tool for building rich documentation for command line applications using result builders and
syntax similar to `SwiftUI`.
## Getting Started
Add this as a package dependency to your command line application.
```swift
let package = Package(
name: "my-tool"
...
dependencies: [
.package(url: "https://git.housh.dev/michael/swift-cli-doc", from: "0.1.0")
],
targets: [
.executableTarget(
name: "my-tool",
dependencies: [
.product(name: "CliDoc", package: "swift-cli-doc")
]
)
]
)
```

View File

@@ -9,7 +9,8 @@ struct Application: ParsableCommand {
subcommands: [ subcommands: [
SectionCommand.self, SectionCommand.self,
VStackCommand.self, VStackCommand.self,
HStackCommand.self HStackCommand.self,
GroupCommand.self
] ]
) )
} }

View File

@@ -0,0 +1,21 @@
import ArgumentParser
import CliDocCore
struct GroupCommand: ParsableCommand {
static let configuration = CommandConfiguration(commandName: "group")
func run() throws {
let group = Group {
"My headline."
"\n"
"Some content".color(.green)
"\n"
"Foo Bar".italic()
}
.color(.blue)
print()
print("\(group.render())")
}
}

Binary file not shown.

View File

@@ -2,6 +2,23 @@
/// ///
/// This allows you to group content together, which can optionally be /// This allows you to group content together, which can optionally be
/// styled. /// styled.
///
/// ### Example:
///
/// ```swift
/// let group = Group {
/// "My headline."
/// "\n"
/// "Some content".color(.green)
/// "\n"
/// "Foo Bar".italic()
/// }
///
/// print(group.render())
/// ```
///
/// ![Group example](group.png)
///
public struct Group<Content: TextNode>: TextNode { public struct Group<Content: TextNode>: TextNode {
@usableFromInline @usableFromInline

View File

@@ -59,7 +59,7 @@ public extension HStack {
/// Style a ``HStack`` by creating a type that conforms to ``HStackStyle`` and use the /// Style a ``HStack`` by creating a type that conforms to ``HStackStyle`` and use the
/// style by calling the ``HStack/style(_:)`` method on your instance. /// style by calling the ``HStack/style(_:)`` method on your instance.
/// ///
public protocol HStackStyle: TextModifier where Content == StackConfiguration {} public protocol HStackStyle: TextModifier where Content == _StackConfiguration {}
public extension HStackStyle where Self == HStackSeparatorStyle { public extension HStackStyle where Self == HStackSeparatorStyle {
/// Apply the given separator on a ``HStack``. /// Apply the given separator on a ``HStack``.
@@ -88,7 +88,7 @@ public struct HStackSeparatorStyle: HStackStyle {
} }
@inlinable @inlinable
public func render(content: StackConfiguration) -> some TextNode { public func render(content: _StackConfiguration) -> some TextNode {
AnySeparatableStackNode(content: content, separator: separator) AnySeparatableStackNode(content: content, separator: separator)
} }
} }

View File

@@ -1,10 +1,14 @@
// swiftlint:disable type_name
/// Represents the content of an ``HStack`` or a ``VStack``. /// Represents the content of an ``HStack`` or a ``VStack``.
/// ///
/// /// This is an internal convenience type, but needs to remain public
public struct StackConfiguration { /// for protcol conformances to work properly.
public struct _StackConfiguration {
public let content: [any TextNode] public let content: [any TextNode]
} }
// swiftlint:enable type_name
/// A helper type that removes empty text nodes, and applies a separtor between /// A helper type that removes empty text nodes, and applies a separtor between
/// the array of text nodes. /// the array of text nodes.
/// ///
@@ -18,7 +22,7 @@ struct AnySeparatableStackNode<Separator: TextNode>: TextNode {
let separator: Separator let separator: Separator
@usableFromInline @usableFromInline
init(content: StackConfiguration, separator: Separator) { init(content: _StackConfiguration, separator: Separator) {
self.content = content.content self.content = content.content
self.separator = separator self.separator = separator
} }

View File

@@ -62,7 +62,7 @@ public extension VStack {
/// Style a ``VStack`` by creating a type that conforms to ``VStackStyle`` and use the /// Style a ``VStack`` by creating a type that conforms to ``VStackStyle`` and use the
/// style by calling the ``VStack/style(_:)`` method on your instance. /// style by calling the ``VStack/style(_:)`` method on your instance.
/// ///
public protocol VStackStyle: TextModifier where Content == StackConfiguration {} public protocol VStackStyle: TextModifier where Content == _StackConfiguration {}
public extension VStackStyle where Self == VStackSeparatorStyle { public extension VStackStyle where Self == VStackSeparatorStyle {
@@ -92,7 +92,7 @@ public struct VStackSeparatorStyle: VStackStyle {
} }
@inlinable @inlinable
public func render(content: StackConfiguration) -> some TextNode { public func render(content: _StackConfiguration) -> some TextNode {
AnySeparatableStackNode(content: content, separator: separator) AnySeparatableStackNode(content: content, separator: separator)
} }
} }

View File

@@ -22,6 +22,26 @@ struct CliDocCoreTests {
} }
} }
#expect(group.render() == "foobar\("baz".blue)") #expect(group.render() == "foobar\("baz".blue)")
let group2 = Group {
VStack {
"My headline."
"Some text."
}
"\n"
HStack {
"Foo"
"Bar"
}
}
.color(.green)
print(group2.render())
#expect(group2.render() == """
My headline.
Some text.
Foo Bar
""".green)
} }
@Test @Test