Skip to content

Commit 15905c9

Browse files
neonichuabertelrud
authored andcommitted
Add template support for creating a command plugin package
This is fairly minimal at the moment, and doesn't try to be a tutorial on how to write command plugins. Needs a unit test. rdar://107288352
1 parent 472e441 commit 15905c9

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

Sources/Commands/PackageTools/Init.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extension SwiftPackageTool {
3131
tool - A package with an executable that uses
3232
Swift Argument Parser. Use this template if you
3333
plan to have a rich set of command-line arguments.
34+
command-plugin - A package that vends a command plugin.
3435
macro - A package that vends a macro.
3536
empty - An empty package with a Package.swift manifest.
3637
"""))

Sources/Workspace/InitPackage.swift

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// This source file is part of the Swift open source project
44
//
5-
// Copyright (c) 2014-2020 Apple Inc. and the Swift project authors
5+
// Copyright (c) 2014-2023 Apple Inc. and the Swift project authors
66
// Licensed under Apache License v2.0 with Runtime Library Exception
77
//
88
// See http://swift.org/LICENSE.txt for license information
@@ -44,7 +44,7 @@ public final class InitPackage {
4444
case library = "library"
4545
case executable = "executable"
4646
case tool = "tool"
47-
case `extension` = "extension"
47+
case commandPlugin = "command-plugin"
4848
case macro = "macro"
4949

5050
public var description: String {
@@ -115,6 +115,7 @@ public final class InitPackage {
115115
// none of it exists, and then act.
116116
try writeManifestFile()
117117
try writeGitIgnore()
118+
try writePlugins()
118119
try writeSources()
119120
try writeTests()
120121
}
@@ -270,6 +271,14 @@ public final class InitPackage {
270271
]),
271272
]
272273
"""
274+
} else if packageType == .commandPlugin {
275+
param += """
276+
.plugin(
277+
name: "\(typeName)",
278+
capability: .command(intent: .custom(verb: "\(typeName)", description: "prints hello world"))
279+
),
280+
]
281+
"""
273282
} else if packageType == .macro {
274283
param += """
275284
// Macro implementation, only built for the host and never part of a client program.
@@ -351,8 +360,44 @@ public final class InitPackage {
351360
}
352361
}
353362

363+
private func writePlugins() throws {
364+
switch packageType {
365+
case .commandPlugin:
366+
let plugins = destinationPath.appending(component: "Plugins")
367+
guard self.fileSystem.exists(plugins) == false else {
368+
return
369+
}
370+
progressReporter?("Creating \(plugins.relative(to: destinationPath))/")
371+
try makeDirectories(plugins)
372+
373+
let moduleDir = plugins.appending(component: "\(pkgname)")
374+
try makeDirectories(moduleDir)
375+
376+
let sourceFileName = "plugin.swift"
377+
let sourceFile = try AbsolutePath(validating: sourceFileName, relativeTo: moduleDir)
378+
379+
let content = """
380+
import PackagePlugin
381+
382+
@main
383+
struct \(typeName): CommandPlugin {
384+
func performCommand(context: PluginContext, arguments: [String]) async throws {
385+
print("Hello, World!")
386+
}
387+
}
388+
"""
389+
390+
try writePackageFile(sourceFile) { stream in
391+
stream.write(content)
392+
}
393+
394+
case .empty, .library, .executable, .tool, .macro:
395+
break
396+
}
397+
}
398+
354399
private func writeSources() throws {
355-
if packageType == .empty {
400+
if packageType == .empty || packageType == .commandPlugin {
356401
return
357402
}
358403

@@ -428,7 +473,7 @@ public final class InitPackage {
428473
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "\(moduleName)Macros", type: "StringifyMacro")
429474
"""
430475

431-
case .empty, .`extension`:
476+
case .empty, .commandPlugin:
432477
throw InternalError("invalid packageType \(packageType)")
433478
}
434479

@@ -444,7 +489,7 @@ public final class InitPackage {
444489

445490
private func writeTests() throws {
446491
switch packageType {
447-
case .empty, .executable, .tool, .`extension`: return
492+
case .empty, .executable, .tool, .commandPlugin: return
448493
default: break
449494
}
450495
let tests = destinationPath.appending("Tests")
@@ -590,7 +635,7 @@ public final class InitPackage {
590635

591636
let testClassFile = try AbsolutePath(validating: "\(moduleName)Tests.swift", relativeTo: testModule)
592637
switch packageType {
593-
case .empty, .`extension`, .executable, .tool: break
638+
case .empty, .commandPlugin, .executable, .tool: break
594639
case .library:
595640
try writeLibraryTestsFile(testClassFile)
596641
case .macro:

0 commit comments

Comments
 (0)