SwiftShortcuts

一个使用 Swift 编写的 iOS 14 捷径创建工具,灵感来自 SwiftUI。

安装

SwiftShortcuts 使用 Swift Package Manager 分发。 要将其安装到项目中,请将其作为依赖项添加到您的 Package.swift 清单文件中

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/a2/swift-shortcuts.git", from: "1.0.0")
    ],
    ...
)

然后在您想要使用它的项目的任何位置导入 SwiftShortcuts

import SwiftShortcuts

开始使用

SwiftShortcuts 的灵感来自 SwiftUI,正如每个 SwiftUI View 都是由其他 View 类型组成一样,每个 Shortcut 也是由其他 Shortcut 类型构建的。 Shortcut 协议的唯一要求是一个名为 body 的实例属性,其类型是另一个 Shortcut

/// A type that represents a user workflow, or a part of one, in the Shortcuts app.
public protocol Shortcut {
    /// The type of shortcut representing the body of this shortcut.
    ///
    /// When you create a custom shortcut, Swift infers this type from your
    /// implementation of the required `body` property.
    associatedtype Body: Shortcut

    /// The contents of the shortcut.
    var body: Body { get }
}

要开始编写您自己的快捷方式,请创建一个符合 Shortcut 协议的类型(例如 struct)。 首先,返回一个带有 “Hello, world!” 文本的 Comment

// main.swift

struct HelloWorldShortcut: Shortcut {
    var body: some Shortcut {
        Comment("Hello, world!")
    }
}

要创建一个可以导入到“捷径”应用程序的文件,请在您的快捷方式上调用 build() 函数,并将 Data 写入文件。

// continued from above

let shortcut = HelloWorldShortcut()
let data = try shortcut.build()
try data.write(to: URL(fileURLWithPath: "Hello World.shortcut"))

现在您可以将 *Hello World.shortcut* 文件共享(例如,通过 AirDrop)到您的设备,它将在“捷径”应用程序中打开。 遗憾的是,iOS 13 不支持打开序列化的 .shortcut 文件。

示例

电量低时发出警告

BatteryLevel 快捷方式的输出保存到 OutputVariable,稍后在 ShowResult 快捷方式中引用该值。

// Swift 5.2
import SwiftShortcuts

struct BatteryLevelShortcut: Shortcut {
    @OutputVariable var batteryLevel: Variable

    var body: some Shortcut {
        ShortcutGroup {
            Comment("This Shortcut was generated in Swift.")
            BatteryLevel()
                .savingOutput(to: $batteryLevel)
            If(batteryLevel < Number(20), then: {
                SetLowPowerMode(true)
                ShowResult("Your battery level is \(batteryLevel)%; you might want to charge soon.")
            }, else: {
                ShowResult("Your battery level is \(batteryLevel)%; you're probably fine for now.")
            })
        }
    }
}

一起拍手

利用 usingResult() 函数将快捷方式输出链接到快捷方式输入。

// Swift 5.2
import SwiftShortcuts

struct ClapAlongShortcut: Shortcut {
    var body: some Shortcut {
        ShortcutGroup {
            Comment("This Shortcut was generated in Swift.")
            AskForInput(prompt: "WHAT 👏 DO 👏 YOU 👏 WANT 👏 TO 👏 SAY")
                .usingResult { providedInput in
                    ChangeCase(variable: providedInput, target: .value(.uppercase))
                }
                .usingResult { changedCaseText in
                    ReplaceText(variable: changedCaseText, target: "[\\s]", replacement: " 👏 ", isRegularExpression: true)
                }
                .usingResult { updatedText in
                    ChooseFromMenu(items: [
                        MenuItem(label: "Share") {
                            Share(input: updatedText)
                        },
                        MenuItem(label: "Copy to Clipboard") {
                            CopyToClipboard(content: updatedText)
                        },
                    ])
                }
        }
    }
}

使用 small.cat 缩短链接

一个更复杂的示例,使用 small.cat 服务临时缩短 URL 或一些文本。

// Swift 5.2
import SwiftShortcuts

struct ShortenWithSmallCatShortcut: Shortcut {
    @OutputVariable var url: Variable
    @OutputVariable var expiry: Variable

    var body: some Shortcut {
        ShortcutGroup {
            GetType(input: .shortcutInput)
                .usingResult { type in
                    If(type == "URL", then: {
                        Text("\(.shortcutInput)")
                    }, else: {
                        GetClipboard()
                    })
                }
                .usingResult { ifResult in
                    URLEncode(input: "\(ifResult)")
                }
                .savingOutput(to: $url)

            ChooseFromMenu(prompt: "Expires in:", items: [
                    MenuItem(label: "10 minutes") {
                        Text("10")
                    },
                    MenuItem(label: "1 hour") {
                        Text("60")
                    },
                    MenuItem(label: "1 day") {
                        Text("1440")
                    },
                    MenuItem(label: "1 week") {
                        Text("10080")
                    },
                ])
                .savingOutput(to: $expiry)

            GetContentsOfURL(method: .POST, url: "https://small.cat/entries", body: .form([
                "entry[duration]": "\(expiry)",
                "entry[value]": "\(url)",
                "utf8": "",
            ])).usingResult { contents in
                GetURLsFromInput(input: "\(contents)")
            }.usingResult { urls in
                FilterFiles(input: urls, filters: .all([
                    NameFilter(beginsWith: "http://small.cat/"),
                    NameFilter(isNot: "http://small.cat/"),
                ]), limit: 1)
            }.usingResult { url in
                ChooseFromMenu(items: [
                    MenuItem(label: "Copy") {
                        CopyToClipboard(content: url)
                    },
                    MenuItem(label: "Share") {
                        Share(input: url)
                    },
                    MenuItem(label: "Show") {
                        ShowAlert(title: "Small.cat", message: "\(url)", showsCancelButton: false)
                    },
                ])
            }
        }
    }
}

设计和目标

SwiftShortcuts 最初名为 ShortcutsSwift,最初的灵感来自 Shortcuts JS。 SwiftShortcuts 和之前的 ShortcutsSwift 都旨在成为 Swift 中类似于 JavaScript 中 Shortcuts JS 的工具。

此版本 SwiftShortcuts 的目标是使使用 Swift 编写“捷径”应用程序工作流程就像在 SwiftUI 中组合 View 一样容易。 正如您在上面看到的,即使是基本的 Shortcut 协议也深受 SwiftUI 的 View 协议的启发。

此存储库不包含每个“捷径”支持的操作,也不包含这些快捷方式的每个可能的参数排列。 请随时贡献缺失的快捷方式类型,甚至测试用例。

许可证

SwiftShortcuts 在 MIT 许可证下可用。 有关更多信息,请参见LICENSE文件。

贡献与支持

灵感来自Publish背后的支持模型。

SwiftShortcuts 完全公开开发,非常欢迎您的贡献。

此项目不提供基于 GitHub Issues 的支持,而是鼓励用户积极参与其持续开发 — 通过修复他们遇到的任何错误,或者通过改进发现缺乏的文档。

如果您希望进行更改,请打开一个 Pull Request — 即使它只包含您计划更改的草稿,或者重现问题的测试 — 我们可以从那里进一步讨论。

希望您喜欢使用 SwiftShortcuts!