XUtils

SwiftFormat

A code library and command-line formatting tool for reformatting Swift code.


1) Create a BuildTools folder and Package.swift

  1. Create a folder called BuildTools in the same folder as your xcodeproj file
  2. In this folder, create a file called Package.swift, with the following contents:
// 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.54.0"),
    ],
    targets: [.target(name: "BuildTools", path: "")]
)
  1. If you are running Xcode 11.4 or later, in the BuildTools folder create a file called Empty.swift with nothing in it. This is to satisfy a change in Swift Package Manager.

2) Add a Build phase to your app target

  1. Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab

  2. Add a New Run Script Phase by clicking the little plus icon in the top left

  3. Uncheck the Based on dependency analysis checkbox

  4. Drag the new Run Script phase above the Compile Sources phase, expand it and paste the following script:

    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"
    

You can also use swift run -c release --package-path BuildTools swiftformat "$SRCROOT" if you need a more complex script and cd BuildTools breaks stuff.

NOTE: You may wish to check BuildTools/Package.swift into your source control so that the version used by your run-script phase is kept in version control. It is recommended to add the following to your .gitignore file: BuildTools/.build and BuildTools/.swiftpm.

NOTE (2): If you are using Xcode 15 or later, make sure that the ENABLE_USER_SCRIPT_SANDBOXING (aka “User Script Sandboxing”) option is set to NO, otherwise SwiftFormat won’t be able to run correctly.

Using CocoaPods

1) Add the SwiftFormat CLI to your Podfile

  1. Add the swiftformat binary to your project directory via CocoaPods, by adding the following line to your Podfile then running pod install:

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

NOTE: This will only install the pre-built command-line app, not the source code for the SwiftFormat framework.

NOTE (2): When installing this way, GateKeeper may block swiftformat from running until you open it manually the first time by right-clicking in the Finder and selecting “Open”.

2) Add a Build phase to your app target

  1. Click on your project in the file list, choose your target under TARGETS, click the Build Phases tab

  2. Add a New Run Script Phase by clicking the little plus icon in the top left

  3. Uncheck the Based on dependency analysis checkbox

  4. Drag the new Run Script phase above the Compile Sources phase, expand it and paste the following script:

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

Alternative: Locally installed SwiftFormat

Alternatively, you could use a locally installed swiftformat command-line tool instead by putting the following in your Run Script build phase:

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

This is not recommended for shared projects however, as different team members using different versions of SwiftFormat may result in noise in the commit history as code gets reformatted inconsistently.

If you installed SwiftFormat via Homebrew on Apple Silicon, you might experience this warning:

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

That is because Homebrew on Apple Silicon installs the binaries into the /opt/homebrew/bin folder by default. To instruct Xcode where to find SwiftFormat, you can either add /opt/homebrew/bin to the PATH environment variable in your build phase

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

or you can create a symbolic link in /usr/local/bin pointing to the actual binary:

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

Swift Package Manager plugin

You can use SwiftFormat as a SwiftPM command plugin.

NOTE: Swift 5.6 or higher is required. Add the package to your dependencies in your Package.swift file.

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

The plugin will find an existing .swiftformat in your package root folder and honor it automatically.

Trigger Plugin From Command-Line

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

You can limit the formatting to a particular target with --target option.

You can also specify SwiftFormat arguments, e.g. --swiftversion.

Example

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

Trigger Plugin From Xcode

In Xcode 14 you can trigger the command plugin execution for a Swift package or an Xcode project.

For an Xcode project the project’s main directory will be processed and the --target option will be ignored.

You can also specify SwiftFormat arguments, e.g. --swiftversion.

Run plugin in Xcode 14

Via AppleScript

To run SwiftFormat on the frontmost Xcode document (project or workspace) you can use the following 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

Some Apps you can trigger this from are BetterTouchTool, Alfred or Keyboard Maestro. Another option is to define a QuickAction for Xcode via Automator and then assign a keyboard shortcut for it in the System Preferences.

VSCode plugin

If you prefer to use Microsoft’s VSCode editor for writing Swift, Valentin Knabel has created a VSCode plugin for SwiftFormat.

Sublime Text plugin

If you prefer to use the Sublime Text editor, try the Sublime-Swift-Format plugin by Aerobounce.

Nova plugin

If you prefer to use the Nova editor, try the SwiftFormat extension by Pádraig Ó Cinnéide.

Git pre-commit hook

  1. Follow the instructions for installing the SwiftFormat command-line tool.

  2. Install git-format-staged.

  3. Edit or create a .git/hooks/pre-commit file in your project folder. The .git folder is hidden but should already exist if you are using Git with your project, so open it with the terminal, or the Finder’s Go > Go to Folder... menu.

  4. Add the following line in the pre-commit file. The {} will be replaced automatically by the path to the Swift file being formatted:

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

    (Note that this example uses your locally installed version of SwiftFormat, not a separate copy in your project repository. You can replace swiftformat with the path to a copy inside your project if you prefer.)

  5. enable the hook by typing chmod +x .git/hooks/pre-commit in the terminal.

The pre-commit hook will now run whenever you run git commit. Running git commit --no-verify will skip the pre-commit hook.

NOTE: If you are using Git via a GUI client such as Tower, additional steps may be needed.

NOTE (2): Unlike the Xcode build phase approach, git pre-commit hook won’t be checked in to source control, and there’s no way to guarantee that all users of the project are using the same version of SwiftFormat. For a collaborative project, you might want to consider a post-commit hook instead, which would run on your continuous integration server.

GitHub Actions

  1. SwiftFormat comes preinstalled on all macOS GitHub-hosted runners. If you are self hosting you will need to ensure SwiftFormat is installed on your runner.
  2. Create a GitHub Actions workflow using SwiftFormat, passing the --reporter github-actions-log command line option. The following example action lints pull requests using SwiftFormat, reporting warnings using the GitHub Actions log.

”`yaml

format options

–allman true –indent tab # tabs FTW!

file options

–exclude Pods


Articles

  • coming soon...