SwiftFormat 0.54.3

SwiftFormat 0.54.3

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最新发布2024年7月
SPM支持 SPM

Nick Lockwood 维护。



  • Nick Lockwood

PayPal Build Codecov Swift 4.2 License Mastodon

目录

这是什么?

SwiftFormat 是一个用于在 macOS 或 Linux 上重格式化 Swift 代码的代码库和命令行工具。

SwiftFormat 远远超出了您可能期望的代码格式化工具所能做到的。除了调整空白之外,它还可以插入或删除隐式的 self,删除多余的括号,并纠正许多与标准 Swift 习惯用法不符的其他偏差。

我为什么要这样做呢?

许多程序员有自己的代码格式化偏好,而其他人似乎对现有的项目格式化约定视而不见(这可能会让他们的同事感到沮丧)。

当协作进行项目时,约定一个统一的编码风格可能会有所帮助,但手动强制执行它既繁琐又容易出错,如果某些参与者对此更加认真,还可能导致争论。

拥有一个可以自动强制执行统一风格的工具可以消除这些问题,让你可以专注于代码的行为而不是它的表现。

我该如何安装它?

这取决于 - 你可以使用多种方式使用SwiftFormat

  1. 作为一个需要手动运行的命令行工具,或者作为某些其他工具链的一部分
  2. 作为一个源代码编辑扩展,你可以通过Xcode中的编辑 > SwiftFormat菜单来调用它
  3. 在你的Xcode项目中作为构建阶段,这样每次你按下Cmd-R或Cmd-B时都会运行,或者
  4. 作为Git的预提交钩子,在你提交更改之前运行于任何已更改的文件上

命令行工具

注意:如果你在macOS 10.14.3或更早的版本上使用以下任何方法安装SwiftFormat且启动时崩溃,你可能需要安装Swift 5命令行工具运行时支持。有关详细信息,请参阅已知问题

安装

你可以在macOS或Linux上使用Homebrew安装swiftformat命令行工具。假设你已经安装了Homebrew,只需输入

$ brew install swiftformat

来更新到最新版本

$ brew upgrade swiftformat

或者,你可以使用Mint在macOS或Linux上安装此工具,如下所示

$ mint install nicklockwood/SwiftFormat

或者,如果你更喜欢,你可以在macOS、Linux或Windows上手动检查并构建SwiftFormat,如下所示

$ git clone https://github.com/nicklockwood/SwiftFormat
$ cd SwiftFormat
$ swift build -c release

如果您要将SwiftFormat安装到您的项目目录中,您可以在macOS上使用CocoaPods,以自动安装swiftformat二进制文件以及您的其他pods - 有关Xcode构建阶段说明的详细信息,请参阅下面的说明。

另一种选择是将二进制文件artifactsbundle包含在您的Package.swift中。

.binaryTarget(
    name: "swiftformat",
    url: "https://github.com/nicklockwood/SwiftFormat/releases/download/0.49.12/swiftformat-macos.artifactbundle.zip",
    checksum: "CHECKSUM"
),

如果您不想使用包管理器,您可以手动构建命令行应用程序。

  1. 打开SwiftFormat.xcodeproj并构建SwiftFormat (Application)方案。

  2. swiftformat二进制文件拖放到/usr/local/bin/(这是一个隐藏文件夹,但您可以使用Finder的转到 > 转到文件夹...菜单打开它)。

  3. 使用您喜欢的文本编辑器打开~/.bash_profile(这是一个隐藏文件,但您可以在终端中输入open ~/.bash_profile以打开它)。

  4. 将以下行添加到文件中:alias swiftformat="/usr/local/bin/swiftformat --indent 4"(您可以省略--indent 4,或用其他内容替换。运行swiftformat --help以查看可用选项)。

  5. 保存.bash_profile文件并运行命令source ~/.bash_profile以便应用更改。

用法

如果您遵循了上面的安装说明,现在您可以在终端中键入

$ swiftformat .

(这是命令后面的一个空格和一个点)以格式化当前目录中的任何Swift文件。在.的位置,您也可以输入要格式化的文件或目录的绝对路径或相对路径。

警告:swiftformat .会改写当前目录及其子目录中找到的任何Swift文件。如果在您的家目录中运行它,可能会刷新您硬盘上的每个Swift文件。

为了安全使用,请执行以下操作:

  1. 选择一个要应用更改的文件或目录。

  2. 确保已在git(或您使用的任何源代码管理系统中)安全地将所有更改提交到该代码。

  3. (可选)在终端中,键入swiftformat --inferoptions "/path/to/your/code/"。这将建议一组用于匹配您的现有项目样式的格式化选项(但是,您可以选择忽略这些选项并使用默认选项,或您自己的设置)。

    路径可以指向单个Swift文件或包含文件的目录。它可以是绝对的,也可以是相对于当前目录的。路径上的双引号是可选的,但如果路径包含空格,则必须使用引号,或者使用\转义每个空格。您可以包含多个使用空格分隔的路径。

  4. 在终端中,键入swiftformat "/path/to/your/code/"。与路径相关的规则相同,允许使用多个以空格分隔的路径。

    如果您在第3步中使用了--inferoptions来生成一组建议的选项,应将其复制并粘贴到命令中,可以在源文件路径之前或之后使用。

    如果您已创建一个配置文件,您可以使用--config "/path/to/your/config-file/"指定其路径。或者,如果文件名为.swiftformat并将其放置在正在格式化的项目内部,它将被自动识别。

  5. 按回车键开始格式化。一旦格式化完成,使用您的源代码管理器检查更改,并验证没有引入不希望的更改。如果有,请撤消更改,调整选项并再次尝试。

  6. (可选)提交更改。

按照这些说明应该可以确保您避免灾难性的数据丢失,但在极不可能擦除您的硬盘的情况下,请注意,我对此不承担任何责任

使用标准输入/输出

如果您更喜欢使用Unix管道将SwiftFormat作为命令链的一部分,以下是对文件进行格式化的替代方法

$ cat /path/to/file.swift | swiftformat --output /path/to/file.swift

省略--output /path/to/file.swift参数将使格式化的文件打印到标准输出(stdout)。您也可以将“stdout”显式地作为输出路径传递

$ cat /path/to/file.swift | swiftformat --output stdout

或者,您可以使用>来指定输出路径,如下所示

$ cat /path/to/file.swift | swiftformat > /path/to/file.swift

如果您未提供输入文件,SwiftFormat将自动从标准输入(stdin)获取其输入,但如果立即没有接收到输入则将超时并显示帮助信息。为了更明确,请传递“stdin”作为输入路径

$ cat /path/to/file.swift | swiftformat stdin

当使用stdin时,SwiftFormat无法访问输入文件的文件路径,因此依赖于文件位置的功能(例如,将创建日期插入头注释中,或检测文件路径中的.swiftformat配置文件)将无法工作。为了解决此问题,您可以使用--stdinpath参数提供文件路径

$ cat /path/to/file.swift | swiftformat stdin --stdinpath /path/to/file.swift

Xcode源代码编辑器扩展

安装

与命令行工具一样,您可以通过Homebrew安装SwiftFormat for Xcode扩展应用。假设您已安装Homebrew,请输入

$ brew install --cask swiftformat-for-xcode

这将在您的应用程序文件夹中安装SwiftFormat for Xcode。双击应用程序打开它,然后按照屏幕上的说明进行操作。

注意:应用程序应正确签名,但如果您在尝试打开它时收到门卫警告,您可以通过右键单击(或按住控制键单击)应用程序并选择打开来绕过此警告。

安装后,要更新到最新版本,请使用以下命令

$ brew upgrade --cask swiftformat-for-xcode

另外,如果您不想使用Homebrew,您可以在GitHub发行版页面上找到SwiftFormat for Xcode应用的最新版本。下载并解压缩zip存档,然后将SwiftFormat for Xcode.app拖到您的Applications文件夹中。

用法

启动应用程序并重新启动Xcode后,您将在Xcode的编辑菜单下找到一个SwiftFormat选项。如果SwiftFormat菜单没有出现,[此线程](https://github.com/nicklockwood/SwiftFormat/issues/494/hovercard)可能会有所帮助。

您可以使用SwiftFormat for Xcode主机应用程序配置格式化规则选项。目前无法按项目覆盖这些设置,但是您可以使用文件菜单导入和导出不同的配置。每次您切换项目时都需要这样做。

配置文件的格式在下面的配置部分中描述。

注意:SwiftFormat for Xcode无法自动检测导入的配置文件的更改。如果您更新了项目的.swiftformat文件,您需要手动将该文件重新导入到SwiftFormat for Xcode,以便Xcode源代码编辑器扩展使用新的配置。

Xcode构建阶段

注意:添加此脚本将覆盖您正在工作的源文件,这会有清除撤销历史记录的讨厌副作用。您可能希望在测试目标而不是主目标中添加脚本,这样它只会在运行单元测试时被调用,而不会在每次构建应用时都调用。

或者,您可能希望在正常的构建过程中作为代码检查的一部分运行SwiftFormat,然后手动运行格式化,或者作为更不频繁的构建目标(例如测试)的一部分。

使用Swift包管理器

要将SwiftFormat设置为Xcode构建阶段,请执行以下操作

1) 创建一个BuildTools文件夹并创建Package.swift文件

  1. 在你的xcodeproj文件相同的文件夹中创建一个名为BuildTools的文件夹
  2. 在此文件夹中创建一个名为Package.swift的文件,内容如下
// swift-tools-version:5.1
import PackageDescription

let package = Package(
    name: "BuildTools",
    platforms: [.macOS(.v10_11)],
    dependencies: [
        .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.49.0"),
    ],
    targets: [.target(name: "BuildTools", path: "")]
)
  1. 如果在Xcode 11.4或更高版本运行,在BuildTools文件夹中创建一个空的名为Empty.swift的文件。这是为了满足Swift包管理器的一个更改。

2) 在您的应用程序目标中添加一个构建阶段

  1. 在文件列表中单击您的项目,然后在 TARGETS 下选择您的目标,单击 构建阶段 选项卡

  2. 通过单击左上角的加号图标,添加一个 新运行脚本阶段

  3. 取消勾选 根据依赖性分析 复选框

  4. 将新的 运行脚本 阶段拖放到 编译源代码 阶段上方,打开它并粘贴以下脚本

    cd BuildTools
    SDKROOT=(xcrun --sdk macosx --show-sdk-path)
    #swift package update #Uncomment this line temporarily to update the version used to the latest matching your BuildTools/Package.swift file
    swift run -c release swiftformat "$SRCROOT"

如果您需要更复杂的脚本,并且 cd BuildTools 会破坏一些东西,也可以使用 swift run -c release --package-path BuildTools swiftformat "$SRCROOT"

注意:您可能希望将 BuildTools/Package.swift 上传到源代码管理中,以便保持运行脚本阶段使用的版本在版本控制中。建议将以下内容添加到您的 .gitignore 文件中:BuildTools/.buildBuildTools/.swiftpm

使用 CocoaPods

1) 将 SwiftFormat CLI 添加到您的 Podfile

  1. 使用 CocoaPodsswiftformat 二进制文件添加到您的项目目录中,通过在 Podfile 中添加以下行,然后运行 pod install

    pod 'SwiftFormat/CLI', '~> 0.49'

注意:这将仅安装预构建的命令行应用,而不是 SwiftFormat 框架的源代码。

注意 (2):以这种方式安装时,GateKeeper 可能会阻止 swiftformat 运行,直到您首次通过在 Finder 中右键单击并选择 "打开" 来手动打开它。

2) 在您的应用目标中添加一个构建阶段

  1. 在文件列表中单击您的项目,然后在 TARGETS 下选择您的目标,单击 构建阶段 选项卡

  2. 通过单击左上角的加号图标,添加一个 新运行脚本阶段

  3. 取消勾选 根据依赖性分析 复选框

  4. 将新的 运行脚本 阶段拖放到 编译源代码 阶段上方,打开它并粘贴以下脚本

    "${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" "$SRCROOT"

另一种方法:本地安装 SwiftFormat

或者,您可以在运行脚本构建阶段中输入以下内容,以使用本地安装的 swiftformat 命令行工具:

if which swiftformat >/dev/null; then
  swiftformat .
else
  echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat"
fi

然而,对于共享项目不推荐这样做,因为不同团队成员使用不同版本的 SwiftFormat 可能会导致提交历史中出现不一致的代码重排噪音。

如果在苹果硅芯片上通过 Homebrew 安装 SwiftFormat,您可能会遇到以下警告:

warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat

这是因为 Homebrew 在苹果硅芯片上默认将二进制文件安装到 /opt/homebrew/bin 文件夹中。要指导 Xcode 在哪里查找 SwiftFormat,您可以在构建阶段将 /opt/homebrew/bin 添加到 PATH 环境变量中

if [[ "$(uname -m)" == arm64 ]]; then
    export PATH="/opt/homebrew/bin:$PATH"
fi

if which swiftformat > /dev/null; then
  swiftformat .
else
  echo "warning: SwiftFormat not installed, download from https://github.com/nicklockwood/SwiftFormat"
fi

或者您可以在 /usr/local/bin 中创建一个指向实际二进制的符号链接

ln -s /opt/homebrew/bin/swiftlint /usr/local/bin/swiftlint

Swift Package Manager 插件

您可以将 SwiftFormat 用作 SwiftPM 命令插件。

注意:需要 Swift 5.6 或更高版本。在 Package.swift 文件中将包添加到依赖项中。

dependencies: [
    // ...
    .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.50.4"),
]

插件将在您的包根目录中查找现有的 .swiftformat 并自动遵守它。

从命令行触发插件

swift package plugin --allow-writing-to-package-directory swiftformat

您可以使用--target选项将格式限制在特定的目标上。

您还可以指定SwiftFormat参数,例如--swiftversion

示例

swift package plugin --allow-writing-to-package-directory swiftformat --target MyLibrary --swiftversion 5.6 --verbose

从Xcode触发插件

在Xcode 14中,您可以为Swift包或Xcode项目触发命令插件执行。

对于Xcode项目,将处理项目的主目录,并忽略--target选项。

您还可以指定SwiftFormat参数,例如--swiftversion

Run plugin in Xcode 14

通过AppleScript触发

要运行SwiftFormat在前台的Xcode文档(项目或工作区)上,您可以使用以下AppleScript

tell application "Xcode"
    set frontWindow to the first window
    set myPath to path of document of frontWindow
    do shell script "cd " & myPath & ";cd ..; /usr/local/bin/swiftformat ."
end tell

一些可以触发此操作的应用程序有BetterTouchToolAlfredKeyboard Maestro。另一种选择是通过Automator定义Xcode的QuickAction,然后在系统偏好设置中为它分配快捷键。

VSCode插件

如果您更喜欢使用Microsoft的VSCode编辑器来编写Swift,Valentin Knabel为SwiftFormat创建了一个VSCode插件

Sublime Text插件

如果您更喜欢使用Sublime Text编辑器,尝试使用由Aerobounce编写的Sublime-Swift-Format插件

Git 预提交钩子

  1. 按照安装 SwiftFormat 命令行工具的说明进行操作。

  2. 安装 git-format-staged

  3. 在您的项目文件夹中编辑或创建一个 .git/hooks/pre-commit 文件。.git 文件夹是隐藏的,但在您使用 Git 的情况下应该已经存在,因此请在终端或 Finder 的 前往 > 前往文件夹... 菜单中打开它。

  4. 在预提交文件中添加以下行。{} 将自动替换为正在格式化的 Swift 文件的路径

    #!/bin/bash
    git-format-staged --formatter "swiftformat stdin --stdinpath '{}'" "*.swift"

    (注意,此示例使用的是您本地安装的 SwiftFormat 版本,而不是项目存储库中的单独副本。您可以选择将 swiftformat 替换为您项目内部副本的路径,如果愿意的话。)。

  5. 在终端中输入 chmod +x .git/hooks/pre-commit 启用钩子。

现在,每次您运行 git commit 时,都会运行预提交钩子。运行 git commit --no-verify 会跳过预提交钩子。

注意:如果您正在通过 GUI 客户端(如 Tower)使用 Git,可能需要采取 额外步骤

注意(2):与 Xcode 构建阶段方法不同,git 预提交钩子不会提交到源控制,也无法保证所有项目用户使用相同的 SwiftFormat 版本。对于协作项目,您可能需要考虑使用 后提交 钩子,该钩子将在您的持续集成服务器上运行。

在 CI 使用 Danger

要使用 Danger 安装您的持续集成系统使用的 SwiftFormat,请按照以下步骤操作:

  1. 按照 说明 安装 Danger。

  2. danger-swiftformat 插件添加到您的 Gemfile

  3. 将以下内容添加到您的 Dangerfile

    swiftformat.binary_path = "/path/to/swiftformat" # optional
    swiftformat.additional_args = "--indent tab --self insert" # optional
    swiftformat.check_format(fail_on_error: true)

    注意:建议将 swiftformat 二进制文件添加到项目目录中,以确保每次使用相同的版本(参见上面的 Xcode 构建阶段 指令)。

Bazel 构建过程

如果您使用 Bazel 构建您的 Swift 项目,并想确保仅将格式正确的代码合并到主分支,请尝试使用 rules_swiftformat。该存储库包含 Bazel 规则和宏,用于使用 SwiftFormat 格式化 Swift 源文件,测试格式化文件是否存在于工作区目录中,并将格式化文件复制到工作区目录。

Docker

SwiftFormat 将发行版发布到 GitHub Packages Docker 注册表。要拉取镜像,请调用

$ docker pull ghcr.io/nicklockwood/swiftformat:latest

默认情况下,容器运行 swiftformat . 因此,您需要提供路径,通过参数

docker run --rm -v /local/source/path:/work ghcr.io/nicklockwood/swiftformat:latest /work

或更改工作目录

docker run --rm -v /local/source/path:/work -w /work ghcr.io/nicklockwood/swiftformat:latest

检查安装的 SwiftFormat 版本

docker run --rm ghcr.io/nicklockwood/swiftformat:latest --version

代码检查示例

docker run --rm -v /local/source/path:/work ghcr.io/nicklockwood/swiftformat:latest /work --lint

配置

SwiftFormat 的配置分为 规则选项。规则是 SwiftFormat 库中应用更改的函数。选项是控制规则行为的功能。

选项

可以使用 --options 命令行参数显示 SwiftFormat 中的可用选项。每个选项的默认值在帮助文本中指示。

通过在命令行参数中添加 或创建一个包含在项目目录中的 .swiftformat 配置文件 来配置规则。

某个选项可能影响多个规则。使用 --ruleinfo [rule_name] 命令查看哪个选项影响特定规则,或者查看 Rules.md 文件。

您可以通过在 Swift 文件中的注释中使用 swiftformat:options 指令来配置特定文件或代码范围内的选项。要在源文件内部暂时设置一个或多个选项,请使用以下方式:

// swiftformat:options --indent 2 --allman true

要仅对特定行应用选项覆盖,请使用 :next 修饰符。

// swiftformat:options:next --semicolons inline
doTheThing(); print("Did the thing")

规则

SwiftFormat 包含超过 50 条规则,并且一直在添加新的规则。最新的规则列表可以在 Rules.md 中找到,包括如何使用这些规则的文档。

可以使用命令行中的 --rules 参数在可用的规则列表中显示。规则可以是启用的或禁用的。默认情况下大多数都是启用的。禁用的规则在用 --rules 显示时会被标记为 "(disabled)"。

您可以使用 --ruleinfo [rule_name] 命令来获取特定规则的信息。传递逗号分隔的规则名列表可以同时获取多个规则的信息,或者在不提供任何参数的情况下使用 --ruleinfo 来获取有关所有规则的信息。

可以使用 --disable 后跟一个或多个逗号分隔的规则名列表,禁用单个规则;或者使用 --enable 后跟规则名来启用启用选项规则。

--disable redundantSelf,trailingClosures
--enable isEmpty

如果您喜欢,也可以使用多个 --enable/--disable 参数,而不是使用逗号。

--disable indent
--disable linebreaks
--disable redundantSelf

或者,您可以使用行继续字符 \ 将单个参数拆分为多行。

--disable          \
    indent,        \
    linebreaks,    \
    redundantSelf

为了避免在 SwiftFormat 更新时自动启用新规则,可以使用以下命令禁用所有规则:

--disable all

然后仅单独启用您想要的规则。或者,使用 --rules 参数来仅启用指定的规则。

--rules indent,linebreaks

如上所述,您可以选择包括多个 --rules 参数,或者使用行继续字符 \ 将规则换行到单独的行上。

--rules redundantSelf
--rules         \
    indent,     \
    linebreaks

要查看将应用哪些规则给特定文件,可以使用 --verbose 命令行选项来强制 SwiftFormat 打印在应用格式化时更多详细日志。**注意**:在详细模式下运行比默认模式慢。

您可以使用 Swift 文件内的注释中的 swiftformat: 指令来禁用特定文件或代码范围内的规则。要在源文件内部暂时代码禁用多个规则,请使用以下方式:

// swiftformat:disable <rule1> [<rule2> [rule<3> ...]]

要再次启用该规则,使用

// swiftformat:enable <rule1> [<rule2> [rule<3> ...]]

要禁用所有规则,使用

// swiftformat:disable all

然后再次使用应为它们启用的命令。

// swiftformat:enable all

要暂时防止将一条或多条规则应用于接下来的一行,请使用

// swiftformat:disable:next <rule1> [<rule2> [rule<3> ...]]
let foo = bar // rule(s) will be disabled for this line
let bar = baz // rule(s) will be re-enabled for this line

在使用 next 指令后,没有必要手动重新启用规则。

**注意**: swiftformat:enable 指令仅用于抵消同一文件中的上一个 swiftformat:disable 指令。不能使用 swiftformat:enable 来启用格式化开始时已经禁用的规则。

Swift版本

SwiftFormat的大部分规则都与版本无关,但有些规则只适用于较新的Swift版本。如果未指定Swift版本,则将自动禁用这些规则,因此为了确保完整的功能可用,您应该指定项目使用的Swift版本。

您可以通过两种方式指定Swift版本

首选选项是在项目目录中添加一个.swift-version文件。这是一个包含您的项目支持的最小Swift版本的文本文件,也是其他工具已经使用的标准。

.swift-version文件具有层次性;如果您的项目有使用不同Swift版本的子模块,您可以为这些目录添加单独的.swift-version文件。

另外一种指定Swift版本的方法是使用--swiftversion命令行参数。请注意,如果在处理时遇到任何.swift-version文件,将覆盖此选项。

配置文件

虽然可以通过使用上面详细说明的命令行选项规则直接配置SwiftFormat,但有时创建一个配置文件会更方便,该文件可以添加到项目中并与其他开发者共享。

SwiftFormat配置文件由一个或多个命令行选项组成,分别放在单独的行上,例如

--allman true
--indent tab
--disable elseOnSameLine,semicolons

在格式化时,SwiftFormat将自动检查每个子目录中是否存在.swiftformat文件,并将找到的任何选项应用于该目录中的文件。

这允许您仅针对特定的文件目录覆盖某些规则或格式化选项。您还可以使用--exclude指定相对于该目录的排除文件,这可能比在顶层指定它们更方便。

--exclude Pods,Generated

--exclude选项接受一个逗号分隔的文件或目录路径列表,用于排除格式化。排除路径相对于包含--exclude命令的配置文件。排除路径可以包括使用的Unix "Glob"语法中的通配符,如下所述。

名为".swiftformat"的配置文件将自动处理,但是,您可以使用--config "path/to/config/file"命令行参数选择用于格式化的其他配置文件。使用--config选择的配置文件不需要命名为".swiftformat",并且可以位于项目目录之外。

配置文件格式设计为可手动编辑。您可以为可读性包括空行,也可以使用井号前缀(#)添加注释,例如:

# format options
--allman true
--indent tab # tabs FTW!

# file options
--exclude Pods

# rules
--disable elseOnSameLine,semicolons

如果您不想手动编辑配置文件,可以使用SwiftFormat for Xcode应用程序来编辑配置并导出配置文件。您还可以使用swiftformat命令行工具的--inferoptions命令从现有项目生成配置文件,如下所示

$ cd /path/to/project
$ swiftformat --inferoptions . --output .swiftformat

glob模式

当使用--exclude选项排除格式化文件时,您可能希望使用通配符路径(也就是“glob模式”)来匹配所有符合特定命名约定而无需手动列出它们的文件。

SwiftFormat的glob语法基于Ruby的实现,与Unix标准略有不同。下面列出了支持的模板

  • * - 一个星号可以匹配文件名中的零个或多个字符,但不能匹配/

  • ** - 双星号将匹配任何内容,包括一个或多个/

  • ? - 一个问号将匹配任何单个字符,但不能匹配/

  • [abc] - 匹配方括号内的任何单个字符。

  • [a-z] - 匹配方括号内指定范围内的单个字符。

  • {foo,bar} - 匹配大括号内用逗号分隔的任一字符串。

实例

  • foo.swift - 匹配与配置文件相同的目录中的“foo.swift”文件。

  • *.swift - 匹配与配置文件相同的目录中的任何Swift文件。

  • foo/bar.swift - 匹配“foo”目录中的“bar.swift”文件。

  • **/foo.swift - 匹配项目中的任何名为“foo.swift”的文件。

  • **/*.swift - 匹配项目中的任何Swift文件。

  • **/Generated - 匹配项目中名为“Generated”的任何文件夹。

  • **/*_generated.swift - 匹配项目中后缀为“_generated”的任何Swift文件。

代码检查

SwiftFormat主要设计为格式化工具而不是代码检查工具,即它的设计是为了修复您的代码,而不是告诉您代码哪里有问题。然而,有时候在某些不希望实际更改代码的上下文中验证代码的格式是有用的。

一个典型的例子会是作为CI(持续集成)流程的一部分,你可能希望建立一个自动脚本,用于检查提交的代码中是否有违例风格的问题。虽然你可以使用像SwiftLint这样的独立工具来做这件事,但能够根据你在应用时的规则来验证格式是有道理的。

要把SwiftFormat运行成检查器,可以使用--lint命令行选项。

$ swiftformat --lint path/to/project

这将使用与格式化模式相同的规则,以及所有相同的配置选项。不过,它不会修改任何文件。相反,SwiftFormat会在内存中格式化每个文件,然后将格式化后的结果与输入进行比较,报告哪些行需要更改。

--lint选项与--dryrun相似,但--lint会为所有需要更改的行返回警告。如果在--lint模式下检测到任何更改,它将返回一个非零错误代码(参见下文的错误代码),这对于你希望在CI服务器上使构建步骤失败时非常有用。

如果你希望--lint不使构建失败,你可以使用--lenient选项来强制SwiftFormat在--lint模式下,即使发现格式化问题也返回成功。

$ swiftformat --lint --lenient path/to/project

默认情况下,--lint只报告需要格式化的行,但你也可以通过使用额外的--verbose标志来显示有关哪些文件被检查的额外信息,即使没有任何变化也是一样。

如果你不希望看到每次格式化更改时的警告,可以使用--quiet标志来抑制除错误以外的所有输出。

有时你可能希望自动格式化某些规则,但只检查其他规则。要做到这一点,在配置文件中使用--lintonly选项来指定只在--lint模式下应用的规定。

--rules braces,indent
--lintonly trailingClosures,unusedArguments

错误代码

swiftformat命令行工具总是以以下之一退出:

  • 0 - 成功。这将在格式化运行成功或–lint未检测到违规时返回。
  • 1 - 检查失败。仅在–lint模式下,如果输入需要格式化时返回此代码。
  • 70 - 程序错误。如果输入或配置参数有问题时返回此代码。

缓存

SwiftFormat使用缓存文件来避免重新格式化未发生更改的文件。对于大型项目,这可以显著减少处理时间。

默认情况下,缓存存储在 macOS 上的 ~/Library/Caches/com.charcoaldesign.swiftformat,或在 Linux 上的 /var/tmp/com.charcoaldesign.swiftformat。使用命令行选项 --cache ignore 来忽略缓存版本并重新对所有文件应用格式。或者,您可以使用 --cache clear 来删除缓存(或者您可以直接手动删除缓存文件)。

缓存在所有项目之间是共享的。文件相当小,因为它只存储每个文件的路径和大小,而不是内容。如果您开始因为缓存太大而出现性能下降,您可能需要考虑为每个项目使用单独的缓存文件。

您可以通过将路径作为 --cache 选项的值传递来指定自定义缓存文件位置。例如,您可能希望将缓存文件存储在您的项目目录中。如果您想在不同项目用户之间共享缓存文件,将其检查入版本库是可以的,因为缓存中存储的路径相对于格式化文件的当前位置是相对的。

文件头

SwiftFormat 可配置为在每个文件的文件头中删除或替换模板。将“文件头注释”定义为从头几个非空行开始并以至少一个空行之后的注释块。这可以是一个单独的注释体,也可以是连续几行的多个注释。

// This is a header comment
// This is a regular comment
func foo(bar: Int) -> Void { ... }

头部模板是您使用 --header 命令行选项提供的字符串。传递 ignore(默认值)将会保留文件头注释不变。传递 strip 或空字符串 "" 将会移除它们。如果您要提供一个自定义头部模板,其格式如下

对于单行模板:--header "版权所有 (C) 2017 Foobar Industries"

对于多行注释,用 \n 标记换行:--header "第一行\n第二行"

如果您希望在模板中包含 Swift 注释标记,可以这样操作:--header "/*--- 头部注释 ---*/"

如果您不包含注释标记,模板中的每一行都将前缀为 // 和一个空格。

在注释头版权声明中包含文件名、创建日期和/或当前年是一个常见的做法。为此,您可以使用以下占位符

  • {file} - 文件名
  • {year} - 当前年份
  • {created} - 文件被创建的日期
  • {created.year} - 文件被创建的年份

例如,以下头部模板

--header "{file}\nCopyright (c) {year} Foobar Industries\nCreated by John Smith on {created}."

将将被格式化为

// SomeFile.swift
// Copyright (c) 2019 Foobar Industries
// Created by John Smith on 01/02/2016.

注意: {year} 的值和 {created} 日期格式取决于运行脚本的机器的当前区域设置和时区。

FAQ

Q.它与SwiftLint有何不同?

A. SwiftLint主要设计用于寻找并报告代码嗅探和风格违规。SwiftFormat则设计用于修复这些问题。虽然SwiftLint可以修正一些问题,SwiftFormat也有一些对检查的支持,但它们的主要功能是不同的。

Q. SwiftFormat和SwiftLint可以一起使用吗?

A. 当然可以!这两种工具推崇的样式规则相当相似,并且SwiftFormat甚至可以修复SwiftLint警告但没有自动修正的某些风格违规。

Q. SwiftFormat支持哪些平台?

A. SwiftFormat在macOS 10.13(High Sierra)及以上系统上运行,还可以在Ubuntu Linux和Windows上运行。

Q. 支持哪些Swift版本?

A. SwiftFormat的框架和命令行工具可以用Swift 4.2及以上版本编译,并可以格式化Swift 4.x或5.x编写的程序。Swift 3.x不再被积极支持。如果您仍在使用Swift 3.x或更早版本,并且发现SwiftFormat打破了您的代码,那么最好的解决方案可能是指回到早期版本的SwiftFormat,或者只启用规则的小子集。使用--swiftversion参数启用适用于后续Swift版本的特定规则。

Q. SwiftFormat做出了我不想看到的变化。我如何找出哪些规则需要禁用?

A. 如果您使用--verbose选项运行SwiftFormat,它将告诉您已应用于每个文件的规则。然后您可以使用--disable参数有选择地禁用某些规则(如下文所述)。

*Q. 我团队的人们安装了不同的SwiftFormat版本。我们如何确保一致的格式化?

A. 您可以在项目中的.swiftformat文件中指定一个--minversion参数,如果开发人员尝试使用较旧的SwiftFormat版本,则构建将失败。

Q. 如何修改格式化规则?

A. 许多配置选项在命令行接口或.swiftformat配置文件中公开。您可以手动设置这些选项,或者使用--inferoptions参数自动从现有项目中生成配置。

如果有一些您不喜欢的规则,并且这些规则不能通过命令行选项进行配置以满足您的喜好,则可以使用带有逗号分隔的规则名称的--disable参数禁用一个或多个规则。您可以使用--rules参数显示所有受支持的规则列表,它们的行为在README本节的上方进行了文档记录。

如果您使用的是Xcode源代码编辑器扩展,则可以利用SwiftFormat for Xcode主应用来配置规则和选项。遗憾的是,由于扩展API的限制,无法按项目范围进行配置。

如果不想暴露您想要的选项,禁用规则也无法解决问题,则规则是在Rules.swift文件中实现的,因此您可以修改它们并构建一个新的命令行工具版本。如果您认为您的更改可能对所有人都有用,请提交一个拉取请求。

Q.我不想在升级SwiftFormat时惊讶于新添加的规则。我如何防止这种情况?

A. 您可以使用--rules参数来指定要运行的规则列表。如果添加了新规则,如果您已经在SwiftFormat配置中指定了--rules列表,则它们不会被启用。

Q. 为什么我无法设置缩进宽度或在SwiftFormat for Xcode选项中选择制表符或空格?

缩进宽度和制表符/空格可以在Xcode中按项目基础进行配置。您将在右侧侧边栏的文件检查器中的“文本设置”下找到此选项。

Q. 应用SwiftFormat后,我的代码无法编译。这是错误吗?

A. SwiftFormat理想状态下永远不会破坏您的代码。检查已知问题,如果它尚未列出或建议的解决方案无法解决问题,请在GitHub上提交问题

Q. 我可以使用SwiftFormat在不更改代码的情况下进行代码审查吗?

A. 是的,请参阅上方的审查部分以获取详细信息。

Q. 我可以在另一个应用程序中使用SwiftFormat.framework吗?

A. 是的,SwiftFormat框架可以包含在应用程序或测试目标中,除了格式化之外,还可以用于许多类型的Swift源代码的解析和处理。SwiftFormat框架作为CocoaPod提供,便于集成。

已知的常见问题

  • 当使用Xcode源代码编辑器扩展时,SwiftFormat菜单有时会从Xcode中消失。如果发生这种情况,请尝试暂时移动或重命名Xcode,然后将其改回。如果不起作用,则此线程中的建议可能有所帮助。链接到问题

  • enumNamespaces规则用枚举替换只有静态成员的类。如果类被继承,或者有代码依赖于该类显示某些运行时行为,则可能会导致程序破坏。要解决这个问题,您可以通过在类声明上方添加一个// swiftformat:disable:next enumNamespaces注释指令来按需修改,或添加--enumnamespaces structs-only以阻止规则应用于类,或完全禁用enumNamespaces规则。

  • redundantVoidReturnType规则可能无意中改变诸如闭包签名之类的类型签名,例如闭包调用一个@discardableResult函数的情况。要解决这个问题,您可以通过在每个调用位置添加一个// swiftformat:disable:next redundantVoidReturnType注释指令来按需修正,或添加--closurevoid preserve到您的配置中,以完全禁用规则(常规函数或方法不受影响)。

  • redundantType规则在默认的--redundanttype inferred模式下使用时,在某些情况下可能会引入模糊的代码。这可以通过使用--redundanttype explicit来解决,或手动从受影响的行移除冗余类型引用,或通过使用// swiftformat:disable:next redundantType注释指令在调用位置禁用规则来解决(或完全禁用redundantType规则)。

  • 如果类型初始化器或工厂方法返回一个隐式展开的可选值,则“redundantType”规则可能在实际上需要的地方移除显式类型。为了解决这个问题,您可以选择使用“--redundanttype explicit”,或者使用“// swiftformat:disable:next redundantType”注释指令在调用位置禁用此规则(或者完全禁用“redundantType”规则)。

  • 在使用“initCoderUnavailable”规则时,如果标记为不可用的“init”在其他程序部分被覆盖,则会导致编译错误。推荐的解决方案是移除覆盖(如果init实际上从未使用过,这不应影响程序行为),或者使用“// swiftformat:disable:next initCoderUnavailable”注释指令禁用覆盖init的规则(或者完全禁用“initCoderUnavailable”规则)。

  • 使用“extensionAccessControl”规则与“--extensionacl on-extension”选项一起时,如果您在另一个文件中定义的内部类型上定义了公共方法,则生成的公共扩展将无法编译。推荐的解决方案是手动移除“public”修饰符(这不会改变程序行为)或禁用“extensionAccessControl”规则。

  • 使用“preferKeyPath”规则时,如果将“compactMap { $0.foo }”转换为“compactMap(.foo)”或“flatMap { $0.foo }”转换为“flatMap(.foo)”,如果“foo”不是“Optional”属性,代码将无法编译。这是由于Swift处理闭包和键路径类型推理方式不同,正如在这里讨论的。推荐的解决方案是在这些情况下将“compactMap”或“flatMap”替换为“map”,这将不会改变代码的行为。

  • 使用“--self remove”选项时,“redundantSelf”规则将删除autoclosure参数中“self”的引用,这可能会改变代码的意义,或导致难以编译。为了解决这个问题,使用“--selfrequired”选项提供要排除的规则的逗号分隔的方法列表。流行的单元测试框架Nimble的“expect”函数默认已排除。如果您使用“--self insert”选项,则这不是问题。

  • 如果您将“SomeClass.self”分配给变量,然后使用该变量实例化类的实例,Swift需要您使用显式的“.init()”,然而,“redundantInit”规则Currently无法检测所有情况,并可能删除“.init”。要解决这个问题,使用“// swiftformat:disable:next redundantInit”注释指令禁用受影响的代码行的规则(或者完全禁用“redundantInit”规则)。

  • “--self insert”选项只能识别本地声明的成员变量,而不是从超类或其他文件中继承的,因此无法为这些变量插入缺少的“self”引用。请注意,情况相反:“--self remove”应该删除全部多余的“self”引用。

  • “trailingClosures”规则如果函数有多个可选闭包参数,或者如果多个函数的签名仅通过闭包参数的名称不同而不同,则可能生成不明确的代码。因此,规则默认限制为匿名闭包参数。您可以使用“--trailingclosures”和“--nevertrailing”参数明确启用或禁用针对特定函数的后置闭包支持。

  • 《isEmpty》规则会将`count == 0`转换为`isEmpty`,即使某些类型没有`isEmpty`方法,例如`NSArray`、《NSDictionary》等。在Swift代码中使用Foundation集合比较罕见,但为了以防万一,该规则默认是禁用的。

  • 如果一个文件以注释开始,并且其后紧接着一个空白行,则《stripHeaders》规则会将其移除。为了避免这种情况,请确保第一行注释后面紧接着是一行代码。

  • 当在macOS 10.14.3或更早版本上使用Xcode 10.2构建的SwiftFormat版本运行时,您可能会遇到崩溃错误“dyld: Library not loaded: @rpath/libswiftCore.dylib”。要修复此问题,您需要安装Swift 5 Runtime Support for Command Line Tools。这些工具默认包含在macOS 10.14.4及以后的版本中。

  • 如果您有一个定义闭包的泛型别名(例如,《ResultCompletion = (Result) -> Void》),并将这个闭包作为泛型函数的参数使用(例如,《func handle(_ completion: ResultCompletion)》),则《opaqueGenericParameters》规则可能会更新函数定义,使用《some》语法(例如,《func handle(_ completion: ResultCompletion)》。由于《some`语法不允许在闭包参数中使用,这会导致代码无法编译。解决方案包括在泛型函数中显式编写闭包(而不是使用《typealias》)或禁用《opaqueGenericParameters》规则(例如,《// swiftformat:next:disable opaqueGenericParameters》)。

  • 如果您使用Xcode 14.0编译macOS,并使用《--swift-version 5.7》配置SwiftFormat,则《genericExtensions》规则可能会通过将格式为《extension Collection where Element == Foo》的扩展更新为《extension Collection`而导致构建失败。这在Xcode 14.0中无法编译,因为该版本的Xcode中macOS SDK没有包含Swift 5.7标准库。[相关论坛讨论](https://forums.swift.org/t/xcode-14-rc-cannot-specialize-protocol-type/60171)。解决方案包括使用《--swift-version 5.6》代替,升级到Xcode 14.1+,或禁用《genericExtensions》规则(例如,《// swiftformat:next:disable genericExtensions》)。

小费罐

SwiftFormat不是商业资助的产品,它是对社区的爱的奉献。如果您觉得它很有用,请考虑捐赠。

Donate via PayPal

致谢

(所有贡献者列表)