Skip to content

Commit a25ba38

Browse files
leogdionclaude
andcommitted
Add skit-analyze implementation plan and dependencies
- Add comprehensive plan for skit-analyze CLI tool (Docs/skit-analyze-plan.md) - Tool will auto-generate updated SyntaxKit library from DSL specifications - Uses Claude API to analyze gaps and generate implementation code - Add ConfigKeyKit to Sources/ for configuration management - Add swift-configuration documentation for reference - Input: folder with dsl.swift + expected.swift (AST auto-generated) - Output: updated SyntaxKit library ready to build Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 18c1e25 commit a25ba38

17 files changed

Lines changed: 15175 additions & 0 deletions

.claude/https_-swiftpackageindex.com-apple-swift-configuration-1.0.0-documentation-configuration.md

Lines changed: 13333 additions & 0 deletions
Large diffs are not rendered by default.

Docs/skit-analyze-plan.md

Lines changed: 954 additions & 0 deletions
Large diffs are not rendered by default.

Sources/ConfigKeyKit/Command.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//
2+
// Command.swift
3+
// ConfigKeyKit
4+
//
5+
// Created by Leo Dion.
6+
// Copyright © 2026 BrightDigit.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or
13+
// sell copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
30+
import Foundation
31+
32+
/// Generic protocol for CLI commands using Swift Configuration
33+
public protocol Command: Sendable {
34+
/// Associated configuration type for this command
35+
associatedtype Config: ConfigurationParseable
36+
37+
/// Command name for CLI parsing
38+
static var commandName: String { get }
39+
40+
/// Abstract description of the command
41+
static var abstract: String { get }
42+
43+
/// Detailed help text for the command
44+
static var helpText: String { get }
45+
46+
/// Initialize command with configuration
47+
init(config: Config)
48+
49+
/// Execute the command asynchronously
50+
func execute() async throws
51+
52+
/// Create a command instance with configuration
53+
static func createInstance() async throws -> Self
54+
}
55+
56+
public extension Command {
57+
/// Print help information for this command
58+
static func printHelp() {
59+
print(helpText)
60+
}
61+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// CommandConfiguration.swift
3+
// ConfigKeyKit
4+
//
5+
// Created by Leo Dion.
6+
// Copyright © 2026 BrightDigit.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or
13+
// sell copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
30+
/// Command configuration for identifying and routing commands
31+
public struct CommandConfiguration {
32+
public let commandName: String
33+
public let abstract: String
34+
35+
public init(commandName: String, abstract: String) {
36+
self.commandName = commandName
37+
self.abstract = abstract
38+
}
39+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//
2+
// CommandLineParser.swift
3+
// ConfigKeyKit
4+
//
5+
// Created by Leo Dion.
6+
// Copyright © 2026 BrightDigit.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or
13+
// sell copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
30+
import Foundation
31+
32+
/// Command line argument parser for Swift Configuration integration
33+
public struct CommandLineParser {
34+
private let arguments: [String]
35+
36+
public init(arguments: [String] = CommandLine.arguments) {
37+
self.arguments = arguments
38+
}
39+
40+
/// Parse the command name from command line arguments
41+
public func parseCommandName() -> String? {
42+
// Skip the executable name (first argument)
43+
guard arguments.count > 1 else { return nil }
44+
let commandCandidate = arguments[1]
45+
46+
// If it starts with '--', it's not a command but a global option
47+
if commandCandidate.hasPrefix("--") {
48+
return nil
49+
}
50+
51+
return commandCandidate
52+
}
53+
54+
/// Get all arguments after the command name for command-specific parsing
55+
public func commandArguments() -> [String] {
56+
guard arguments.count > 1 else { return [] }
57+
let commandName = arguments[1]
58+
59+
// If first argument is an option, return all arguments for global parsing
60+
if commandName.hasPrefix("--") {
61+
return Array(arguments.dropFirst())
62+
}
63+
64+
// Return arguments after command name
65+
return Array(arguments.dropFirst(2))
66+
}
67+
68+
/// Check if help was requested
69+
public func isHelpRequested() -> Bool {
70+
arguments.contains { arg in
71+
arg == "--help" || arg == "-h" || arg == "help"
72+
}
73+
}
74+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//
2+
// CommandRegistry.swift
3+
// ConfigKeyKit
4+
//
5+
// Created by Leo Dion.
6+
// Copyright © 2026 BrightDigit.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or
13+
// sell copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
30+
import Foundation
31+
32+
/// Actor-based registry for managing available commands
33+
public actor CommandRegistry {
34+
private var registeredCommands: [String: any Command.Type] = [:]
35+
private var commandMetadata: [String: CommandMetadata] = [:]
36+
37+
/// Metadata about a command
38+
public struct CommandMetadata: Sendable {
39+
public let commandName: String
40+
public let abstract: String
41+
public let helpText: String
42+
}
43+
44+
/// Shared instance
45+
public static let shared = CommandRegistry()
46+
47+
// Internal initializer for testability - allows tests to create isolated instances
48+
internal init() {}
49+
50+
/// Register a command type with the registry
51+
public func register<T: Command>(_ commandType: T.Type) {
52+
registeredCommands[T.commandName] = commandType
53+
commandMetadata[T.commandName] = CommandMetadata(
54+
commandName: T.commandName,
55+
abstract: T.abstract,
56+
helpText: T.helpText
57+
)
58+
}
59+
60+
/// Get all registered command names
61+
public var availableCommands: [String] {
62+
Array(registeredCommands.keys).sorted()
63+
}
64+
65+
/// Get command metadata
66+
public func metadata(for name: String) -> CommandMetadata? {
67+
commandMetadata[name]
68+
}
69+
70+
/// Get command type for the given name
71+
public func commandType(named name: String) -> (any Command.Type)? {
72+
return registeredCommands[name]
73+
}
74+
75+
/// Create a command instance dynamically with automatic config parsing
76+
public func createCommand(named name: String) async throws -> any Command {
77+
guard let commandType = registeredCommands[name] else {
78+
throw CommandRegistryError.unknownCommand(name)
79+
}
80+
81+
return try await commandType.createInstance()
82+
}
83+
84+
/// Check if a command is registered
85+
public func isRegistered(_ name: String) -> Bool {
86+
return registeredCommands[name] != nil
87+
}
88+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// CommandRegistryError.swift
3+
// ConfigKeyKit
4+
//
5+
// Created by Leo Dion.
6+
// Copyright © 2026 BrightDigit.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or
13+
// sell copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
30+
public import Foundation
31+
32+
/// Errors that can occur in command registry operations
33+
public enum CommandRegistryError: Error, LocalizedError {
34+
case unknownCommand(String)
35+
36+
public var errorDescription: String? {
37+
switch self {
38+
case .unknownCommand(let name):
39+
return "Unknown command: \(name)"
40+
}
41+
}
42+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//
2+
// ConfigKey+Bool.swift
3+
// MistDemo
4+
//
5+
// Created by Leo Dion.
6+
// Copyright © 2026 BrightDigit.
7+
//
8+
// Permission is hereby granted, free of charge, to any person
9+
// obtaining a copy of this software and associated documentation
10+
// files (the "Software"), to deal in the Software without
11+
// restriction, including without limitation the rights to use,
12+
// copy, modify, merge, publish, distribute, sublicense, and/or
13+
// sell copies of the Software, and to permit persons to whom the
14+
// Software is furnished to do so, subject to the following
15+
// conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be
18+
// included in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22+
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23+
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27+
// OTHER DEALINGS IN THE SOFTWARE.
28+
//
29+
30+
import Foundation
31+
32+
// MARK: - Specialized Initializers for Booleans
33+
34+
extension ConfigKey where Value == Bool {
35+
/// Non-optional default value accessor for booleans
36+
@available(*, deprecated, message: "Use defaultValue directly instead")
37+
public var boolDefault: Bool {
38+
defaultValue // Already non-optional!
39+
}
40+
41+
/// Initialize a boolean configuration key with non-optional default
42+
/// - Parameters:
43+
/// - cli: Command-line argument name
44+
/// - env: Environment variable name
45+
/// - defaultVal: Default value (defaults to false)
46+
public init(cli: String, env: String, default defaultVal: Bool = false) {
47+
self.baseKey = nil
48+
self.styles = [:]
49+
var keys: [ConfigKeySource: String] = [:]
50+
keys[.commandLine] = cli
51+
keys[.environment] = env
52+
self.explicitKeys = keys
53+
self.defaultValue = defaultVal
54+
}
55+
56+
/// Initialize a boolean configuration key from base string
57+
/// - Parameters:
58+
/// - base: Base key string (e.g., "sync.verbose")
59+
/// - envPrefix: Prefix for environment variable (defaults to nil)
60+
/// - defaultVal: Default value (defaults to false)
61+
public init(_ base: String, envPrefix: String? = nil, default defaultVal: Bool = false) {
62+
self.baseKey = base
63+
self.styles = [
64+
.commandLine: StandardNamingStyle.dotSeparated,
65+
.environment: StandardNamingStyle.screamingSnakeCase(prefix: envPrefix),
66+
]
67+
self.explicitKeys = [:]
68+
self.defaultValue = defaultVal
69+
}
70+
}
71+
72+
// Application-specific boolean key helpers should be added in application code

0 commit comments

Comments
 (0)