A command-line tool and Xcode Extension for formatting Swift code

Overview

PayPal Travis Codecov Swift 4.2 License Twitter

Table of Contents

What is this?

SwiftFormat is a code library and command-line tool for reformatting Swift code on macOS or Linux.

SwiftFormat goes above and beyond what you might expect from a code formatter. In addition to adjusting white space it can insert or remove implicit self, remove redundant parentheses, and correct many other deviations from the standard Swift idioms.

Why would I want to do that?

Many programmers have a preferred style for formatting their code, and others seem entirely blind to the existing formatting conventions of a project (to the enragement of their colleagues).

When collaborating on a project, it can be helpful to agree on a common coding style, but enforcing that manually is tedious and error-prone, and can lead to arguments if some participants take it more seriously than others.

Having a tool to automatically enforce a common style eliminates those issues, and lets you focus on the behavior of the code, not its presentation.

How do I install it?

That depends - There are several ways you can use SwiftFormat:

  1. As a command-line tool that you run manually, or as part of some other toolchain
  2. As a Source Editor Extension that you can invoke via the Editor > SwiftFormat menu within Xcode
  3. As a build phase in your Xcode project, so that it runs every time you press Cmd-R or Cmd-B, or
  4. As a Git pre-commit hook, so that it runs on any files you've changed before you check them in

Command-line tool

NOTE: if you are using any of the following methods to install SwiftFormat on macOS 10.14.3 or earlier and are experiencing a crash on launch, you may need to install the Swift 5 Runtime Support for Command Line Tools. See known issues for details.

Installation:

You can install the swiftformat command-line tool on macOS using Homebrew. Assuming you already have Homebrew installed, just type:

$ brew install swiftformat

To update to the latest version once installed:

$ brew upgrade swiftformat

Alternatively, you can install the tool on macOS or Linux by using Mint as follows:

$ mint install nicklockwood/SwiftFormat

And then run it using:

$ mint run swiftformat

Or if you prefer, you can check out and build SwiftFormat manually on macOS or Linux as follows:

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

If you are installing SwiftFormat into your project directory, you can use CocoaPods on macOS to automatically install the swiftformat binary along with your other pods - see the Xcode build phase instructions below for details.

If you would prefer not to use a package manager, you can build the command-line app manually:

  1. open SwiftFormat.xcodeproj and build the SwiftFormat (Application) scheme.

  2. Drag the swiftformat binary into /usr/local/bin/ (this is a hidden folder, but you can use the Finder's Go > Go to Folder... menu to open it).

  3. Open ~/.bash_profile in your favorite text editor (this is a hidden file, but you can type open ~/.bash_profile in the terminal to open it).

  4. Add the following line to the file: alias swiftformat="/usr/local/bin/swiftformat --indent 4" (you can omit the --indent 4, or replace it with something else. Run swiftformat --help to see the available options).

  5. Save the .bash_profile file and run the command source ~/.bash_profile for the changes to take effect.

Usage:

If you followed the installation instructions above, you can now just type

$ swiftformat .

(that's a space and then a period after the command) in the terminal to format any Swift files in the current directory. In place of the ., you can instead type an absolute or relative path to the file or directory that you want to format.

WARNING: swiftformat . will overwrite any Swift files it finds in the current directory, and any subfolders therein. If you run it in your home directory, it will probably reformat every Swift file on your hard drive.

To use it safely, do the following:

  1. Choose a file or directory that you want to apply the changes to.

  2. Make sure that you have committed all your changes to that code safely in git (or whatever source control system you use).

  3. (Optional) In Terminal, type swiftformat --inferoptions "/path/to/your/code/". This will suggest a set of formatting options to use that match your existing project style (but you are free to ignore these and use the defaults, or your own settings if you prefer).

    The path can point to either a single Swift file or a directory of files. It can be either be absolute, or relative to the current directory. The "" quotes around the path are optional, but if the path contains spaces then you either need to use quotes, or escape each space with \. You may include multiple paths separated by spaces.

  4. In Terminal, type swiftformat "/path/to/your/code/". The same rules apply as above with respect to paths, and multiple space-delimited paths are allowed.

    If you used --inferoptions to generate a suggested set of options in step 3, you should copy and paste them into the command, either before or after the path(s) to your source files.

    If you have created a config file, you can specify its path using --config "/path/to/your/config-file/". Alternatively, if you name the file .swiftformat and place it inside the project you are formatting, it will be picked up automatically.

  5. Press enter to begin formatting. Once the formatting is complete, use your source control system to check the changes, and verify that no undesirable changes have been introduced. If they have, revert the changes, tweak the options and try again.

  6. (Optional) commit the changes.

Following these instructions should ensure that you avoid catastrophic data loss, but in the unlikely event that it wipes your hard drive, please note that I accept no responsibility.

Using Standard Input/Output:

If you prefer, you can use unix pipes to include SwiftFormat as part of a command chain. For example, this is an alternative way to format a file:

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

Omitting the --output /path/to/file.swift will print the formatted file to Standard Output (stdout). You can also pass "stdout" explicitly as the output path:

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

Or you can use > to specify the output path as follows:

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

If you do not supply an input file, SwiftFormat will automatically take its input from Standard Input (stdin), but will time-out if no input is received immediately and display the help screen. To make it explicit, pass "stdin" as the input path:

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

When using stdin, SwiftFormat does not have access to the file path of the input, so features that rely on the file location (such as inserting the creation date into header comments, or detecting .swiftformat configuration files in the file path) will not work. To solve this, you can provide the file path using the --stdinpath argument:

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

Xcode source editor extension

Installation:

Like the command-line tool, you can install the SwiftFormat for Xcode extension application via Homebrew. Assuming you already have Homebrew installed, type:

$ brew install --cask swiftformat-for-xcode

This will install SwiftFormat for Xcode in your Applications folder. Double-click the app to launch it, and then follow the on-screen instructions.

NOTE: The app should be correctly signed, but if you get a Gatekeeper warning when trying to open it you can bypass this by right-clicking (or control-clicking) the app and selecting Open.

To update to the latest version once installed use:

$ brew upgrade --cask swiftformat-for-xcode

Alternatively, if you prefer not to use Homebrew, you'll find the latest version of the SwiftFormat for Xcode application inside the EditorExtension folder included in the SwiftFormat repository. Download and unpack the zip archive, then drag SwiftFormat for Xcode.app into your Applications folder.

Usage:

Once you have launched the app and restarted Xcode, you'll find a SwiftFormat option under Xcode's Editor menu.

You can configure the formatting rules and options using the SwiftFormat for Xcode host application. There is currently no way to override these per-project, however, you can import and export different configurations using the File menu. You will need to do this again each time you switch projects.

The format of the configuration file is described in the Config section below.

Note: SwiftFormat for Xcode cannot automatically detect changes to an imported configuration file. If you update the .swiftformat file for your project, you will need to manually re-import that file into SwiftFormat for Xcode in order for the Xcode source editor extension to use the new configuration.

Xcode build phase

NOTE: Adding this script will overwrite your source files as you work on them, which has the annoying side-effect of clearing the undo history. You may wish to add the script to your test target rather than your main target, so that it is invoked only when you run the unit tests, and not every time you build the app.

Alternatively, you might want to consider running SwiftFormat in lint mode as part of your normal build, and then running a formatting pass manually, or as part of a less-frequent build target (such as the tests).

Using Swift Package Manager

To set up SwiftFormat as an Xcode build phase, do the following:

1) Create a BuildTools folder & 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.41.2"),
    ],
    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 phases 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. Drag the new Run Script phase above the Compile Sources phase, expand it and paste the following script:

    cd BuildTools
    SDKROOT=macosx
    #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.

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'

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. 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.

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.

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.

On CI using Danger

To setup SwiftFormat to be used by your continuous integration system using Danger, do the following:

  1. Follow the instructions to setup Danger.

  2. Add the danger-swiftformat plugin to your Gemfile.

  3. Add the following to your Dangerfile:

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

    NOTE: It is recommended to add the swiftformat binary to your project directory to ensure the same version is used each time (see the Xcode build phase instructions above).

Configuration

SwiftFormat's configuration is split between rules and options. Rules are functions in the SwiftFormat library that apply changes to the code. Options are settings that control the behavior of the rules.

Options

The options available in SwiftFormat can be displayed using the --options command-line argument. The default value for each option is indicated in the help text.

Rules are configured by adding --[option_name] [value] to your command-line arguments, or by creating a .swiftformat config file and placing it in your project directory.

A given option may affect multiple rules. Use --ruleinfo [rule_name] command for details about which options affect a given rule, or see the Rules.md file.

You can configure options for specific files or code ranges by using swiftformat:options directive in comments inside your Swift file. To temporarily set one or more options inside a source file, use:

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

To apply an options override only to a particular line, use the :next modifier:

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

Rules

SwiftFormat includes over 50 rules, and new ones are added all the time. An up-to-date list can be found in Rules.md along with documentation for how they are used.

The list of available rules can be displayed within the command-line app using the --rules argument. Rules can be either enabled or disabled. Most are enabled by default. Disabled rules are marked with "(disabled)" when displayed using --rules.

You can use the --ruleinfo [rule_name] command to get information about a specific rule. Pass a comma-delimited list of rule names to get information for multiple rules at once, or use --ruleinfo with no argument for info on all rules.

You can disable rules individually using --disable followed by a list of one or more comma-delimited rule names, or enable opt-in rules using --enable followed by the rule names:

--disable redundantSelf,trailingClosures
--enable isEmpty

If you prefer, you can use multiple --enable/--disable arguments instead of using commas:

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

Alternatively, you can use the line continuation character \ to wrap a single argument over multiple line:

--disable          \
    indent,        \
    linebreaks,    \
    redundantSelf

To avoid automatically opting-in to new rules when SwiftFormat is updated, use the--rules argument to only enable the rules you specify:

--rules indent,linebreaks

As above, you may include multiple --rules arguments, or use the line continuation character \ to wrap the rules onto separate lines:

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

To see exactly which rules were applied to a given file, you can use the --verbose command-line option to force SwiftFormat to print a more detailed log as it applies the formatting. NOTE: running in verbose mode is slower than the default mode.

You can disable rules for specific files or code ranges by using swiftformat: directives in comments inside your Swift file. To temporarily disable one or more rules inside a source file, use:

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

To enable the rule(s) again, use:

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

To disable all rules use:

// swiftformat:disable all

And to enable them all again, use:

// swiftformat:enable all

To temporarily prevent one or more rules being applied to just the next line, use:

// 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

There is no need to manually re-enable a rule after using the next directive.

NOTE: The swiftformat:enable directives only serves to counter a previous swiftformat:disable directive in the same file. It is not possible to use swiftformat:enable to enable a rule that was not already enabled when formatting started.

Swift version

Most SwiftFormat rules are version-agnostic, but some are applicable only to newer Swift versions. These rules will be disabled automatically if the Swift version is not specified, so to make sure that the full functionality is available you should specify the version of Swift that is used by your project.

You can specify the Swift version in one of two ways:

The preferred option is to add a .swift-version file to your project directory. This is a text file that should contain the minimum Swift version supported by your project, and is a standard already used by other tools.

The .swift-version file applies hierarchically; If you have submodules in your project that use a different Swift version, you can add separate .swift-version files to those directories.

The other option to specify the Swift version using the --swiftversion command line argument. Note that this will be overridden by any .swift-version files encountered while processing.

Config file

Although it is possible to configure SwiftFormat directly by using the command-line options and rules detailed above, it is sometimes more convenient to create a configuration file, which can be added to your project and shared with other developers.

A SwiftFormat configuration file consists of one or more command-line options, split onto separate lines, e.g:

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

While formatting, SwiftFormat will automatically check inside each subdirectory for the presence of a .swiftformat file and will apply any options that it finds there to the files in that directory.

This allows you to override certain rules or formatting options just for a particular directory of files. You can also specify excluded files relative to that directory using --exclude, which may be more convenient than specifying them at the top-level:

--exclude Pods,Generated

The --exclude option takes a comma-delimited list of file or directory paths to exclude from formatting. Excluded paths are relative to the config file containing the --exclude command. The excluded paths can include wildcards, specified using Unix "Glob" syntax, as documented below.

Config files named ".swiftformat" will be processed automatically, however, you can select an additional configuration file to use for formatting using the --config "path/to/config/file" command-line argument. A configuration file selected using --config does not need to be named ".swiftformat", and can be located outside of the project directory.

The config file format is designed to be edited by hand. You may include blank lines for readability, and can also add comments using a hash prefix (#), e.g.

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

# file options
--exclude Pods

# rules
--disable elseOnSameLine,semicolons

If you would prefer not to edit the configuration file by hand, you can use the SwiftFormat for Xcode app to edit the configuration and export a configuration file. You can also use the swiftformat command-line-tool's --inferoptions command to generate a config file from your existing project, like this:

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

Globs

When excluding files from formatting using the --exclude option, you may wish to make use of wildcard paths (aka "Globs") to match all files that match a particular naming convention without having to manually list them all.

SwiftFormat's glob syntax is based on Ruby's implementation, which varies slightly from the Unix standard. The following patterns are supported:

  • * - A single star matches zero or more characters in a filename, but not a /.

  • ** - A double star will match anything, including one or more /.

  • ? - A question mark will match any single character except /.

  • [abc] - Matches any single character inside the brackets.

  • [a-z] - Matches a single character in the specified range in the brackets.

  • {foo,bar} - Matches any one of the comma-delimited strings inside the braces.

Examples:

  • foo.swift - Matches the file "foo.swift" in the same directory as the config file.

  • *.swift - Matches any Swift file in the same directory as the config file.

  • foo/bar.swift - Matches the file "bar.swift" in the directory "foo".

  • **/foo.swift - Matches any file named "foo.swift" in the project.

  • **/*.swift - Matches any Swift file in the project.

  • **/Generated - Matches any folder called Generated in the project.

  • **/*_generated.swift - Matches any Swift file with the suffix "_generated" in the project.

Linting

SwiftFormat is primarily designed as a formatter rather than a linter, i.e. it is designed to fix your code rather than tell you what's wrong with it. However, sometimes it can be useful to verify that code has been formatted in a context where it is not desirable to actually change it.

A typical example would be as part of a CI (Continuous Integration) process, where you may wish to have an automated script that checks committed code for style violations. While you can use a separate tool such as SwiftLint for this, it makes sense to be able to validate the formatting against the exact same rules as you are using to apply it.

In order to run SwiftFormat as a linter, you can use the --lint command-line option:

$ swiftformat --lint path/to/project

This runs the same rules as format mode, and all the same configuration options apply, however, no files will be modified. Instead, SwiftFormat will format each file in memory and then compare the result against the input and report the lines that required changes.

The --lint option is similar to --dryrun, but --lint returns warnings for every line that required changes, and will return a nonzero error code if any changes are detected, which is useful if you want it to fail a build step on your CI server.

If you would prefer --lint not to fail your build, you can use the --lenient option to force SwiftFormat to return success in --lint mode even when formatting issues were detected.

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

By default, --lint will only report lines that require formatting, but you can use the additional --verbose flag to display additional info about which files were checked, even if there were no changes needed.

If you would prefer not to see a warning for each and every formatting change, you can use the --quiet flag to suppress all output except errors.

Cache

SwiftFormat uses a cache file to avoid reformatting files that haven't changed. For a large project, this can significantly reduce processing time.

By default, the cache is stored in ~/Library/Caches/com.charcoaldesign.swiftformat on macOS, or /var/tmp/com.charcoaldesign.swiftformat on Linux. Use the command-line option --cache ignore to ignore the cached version and re-apply formatting to all files. Alternatively, you can use --cache clear to delete the cache (or you can just manually delete the cache file).

The cache is shared between all projects. The file is fairly small, as it only stores the path and size for each file, not the contents. If you do start experiencing slowdown due to the cache growing too large, you might want to consider using a separate cache file for each project.

You can specify a custom cache file location by passing a path as the --cache option value. For example, you might want to store the cache file inside your project directory. It is fine to check in the cache file if you want to share it between different users of your project, as the paths stored in the cache are relative to the location of the formatted files.

File headers

SwiftFormat can be configured to strip or replace the header comments in every file with a template. The "header comment" is defined as a comment block that begins on the first nonblank line in the file, and is followed by at least one blank line. This may consist of a single comment body, or multiple comments on consecutive lines:

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

The header template is a string that you provide using the --header command-line option. Passing a value of ignore (the default) will leave the header comments unmodified. Passing strip or an empty string "" will remove them. If you wish to provide a custom header template, the format is as follows:

For a single-line template: --header "Copyright (c) 2017 Foobar Industries"

For a multiline comment, mark linebreaks with \n: --header "First line\nSecond line"

You can optionally include Swift comment markup in the template if you wish: --header "/*--- Header comment ---*/"

If you do not include comment markup, each line in the template will be prepended with // and a single space.

It is common practice to include the file name, creation date and/or the current year in a comment header copyright notice. To do that, you can use the following placeholders:

  • {file} - the name of the file
  • {year} - the current year
  • {created} - the date on which the file was created
  • {created.year} - the year in which the file was created

For example, a header template of:

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

Will be formatted as:

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

NOTE: the {year} value and {created} date format are determined from the current locale and timezone of the machine running the script.

FAQ

Q. How is this different from SwiftLint?

A. SwiftLint is primarily designed to find and report code smells and style violations in your code. SwiftFormat is designed to fix them. While SwiftLint can autocorrect some issues, and SwiftFormat has some support for linting, their primary functions are different.

Q. Can SwiftFormat and SwiftLint be used together?

A. Absolutely! The style rules encouraged by both tools are quite similar, and SwiftFormat even fixes some style violations that SwiftLint warns about but can't currently autocorrect.

Q. What platforms does SwiftFormat support?

A. SwiftFormat works on macOS 10.13 (High Sierra) and above, and also runs on Ubuntu Linux.

Q. What versions of Swift are supported?

A. The SwiftFormat framework and command-line tool can be compiled using Swift 4.2 and above, and can format programs written in Swift 4.x or 5. Swift 3.x is no longer actively supported. If you are still using Swift 3.x or earlier and find that SwiftFormat breaks your code, the best solution is probably to revert to an earlier SwiftFormat release, or enable only a small subset of rules. Use the --swiftversion argument to enable additional rules specific to later Swift versions.

Q. SwiftFormat made changes I didn't want it to. How can I find out which rules to disable?

A. If you run SwiftFormat using the --verbose option, it will tell you which rules were applied to each file. You can then selectively disable certain rules using the --disable argument (see below).

*Q. People on my team have different SwiftFormat versions installed. How can we ensure consistent formatting?

A. You can specify a --minversion argument in your project's .swiftformat` file to fail the build if developers attempt to use an older SwiftFormat version.

Q. How can I modify the formatting rules?

A. Many configuration options are exposed in the command-line interface or .swiftformat configuration file. You can either set these manually, or use the --inferoptions argument to automatically generate the configuration from your existing project.

If there is a rule that you don't like, and which cannot be configured to your liking via the command-line options, you can disable one or more rules by using the --disable argument, followed by the name of the rules, separated by commas. You can display a list of all supported rules using the --rules argument, and their behaviors are documented above this section in the README.

If you are using the Xcode source editor extension, rules and options can be configured using the SwiftFormat for Xcode host application. Unfortunately, due to limitation of the Extensions API, there is no way to configure these on a per-project basis.

If the options you want aren't exposed, and disabling the rule doesn't solve the problem, the rules are implemented in the file Rules.swift, so you can modify them and build a new version of the command-line tool. If you think your changes might be generally useful, make a pull request.

Q. I don't want to be surprised by new rules added when I upgrade SwiftFormat. How can I prevent this?

A. You can use the --rules argument to specify an exclusive list of rules to run. If new rules are added, they won't be enabled if you have specified a --rules list in your SwiftFormat configuration.

Q. Why can't I set the indent width or choose between tabs/spaces in the SwiftFormat for Xcode options?

Indent width and tabs/spaces can be configured in Xcode on a per project-basis. You'll find the option under "Text Settings" in the Files inspector of the right-hand sidebar.

Q. After applying SwiftFormat, my code won't compile. Is that a bug?

A. SwiftFormat should ideally never break your code. Check the known issues, and if it's not already listed there, or the suggested workaround doesn't solve your problem, please open an issue on Github.

Q. Can I use SwiftFormat to lint my code without changing it?

A. Yes, see the linting section above for details.

Q. Can I use the SwiftFormat.framework inside another app?

A. Yes, the SwiftFormat framework can be included in an app or test target, and used for many kinds of parsing and processing of Swift source code besides formatting. The SwiftFormat framework is available as a CocoaPod for easy integration.

Known issues

  • If a type initializer or factory method returns an implicitly unwrapped optional value then the redundantType rule may remove the explicit type in a situation where it's actually required. To work around this you can either use --redundanttype explicit, or use the // swiftformat:disable:next redundantType comment directive to disable the rule at the call site (or just disable the redundantType rule completely).

  • When using the initCoderUnavailable rule, if an init that is marked as unavailable is overridden elsewhere in the program then it will cause a compilation error. The recommended workaround is to remove the override (which shouldn't affect the program behavior if the init was really unused) or use the // swiftformat:disable:next initCoderUnavailable comment directive to disable the rule for the overridden init (or just disable the initCoderUnavailable rule completely).

  • When using the extensionAccessControl rule with the --extensionacl on-extension option, if you have public methods defined on an internal type defined in another file, the resultant public extension will no longer compile. The recommended solution is to manually remove the public modifier (this won't change the program behavior) or disable the extensionAccessControl rule.

  • When using the preferKeyPath rule, conversion of compactMap { $0.foo } to compactMap(\.foo) or flatMap { $0.foo } to flatMap(\.foo) will result in code that fails to compile if foo is not an Optional property. This is due to a difference in the way that Swift handles type inference for closures vs keyPaths, as discussed here. The recommended workaround is to replace compactMap() or flatMap() with map() in these cases, which will not change the behavior of the code.

  • When using the --self remove option, the redundantSelf rule will remove references to self in autoclosure arguments, which may change the meaning of the code, or cause it not to compile. To work around this issue, use the --selfrequired option to provide a comma-delimited list of methods to be excluded from the rule. The expect() function from the popular Nimble unit testing framework is already excluded by default. If you are using the --self insert option then this is not an issue.

  • If you assign SomeClass.self to a variable and then instantiate an instance of the class using that variable, Swift requires that you use an explicit .init(), however, the redundantInit rule is not currently capable of detecting this situation and will remove the .init. To work around this issue, use the // swiftformat:disable:next redundantInit comment directive to disable the rule for any affected lines of code (or just disable the redundantInit rule completely).

  • The --self insert option can only recognize locally declared member variables, not ones inherited from superclasses or extensions in other files, so it cannot insert missing self references for those. Note that the reverse is not true: --self remove should remove all redundant self references.

  • The trailingClosures rule can generate ambiguous code if a function has multiple optional closure arguments, or if multiple functions have signatures differing only by the name of the closure argument. For this reason, the rule is limited to anonymous closure arguments by default. You can use the --trailingclosures and --nevertrailing arguments to explicitly opt in or out of trailing closure support for specific functions.

  • The isEmpty rule will convert count == 0 to isEmpty even for types that do not have an isEmpty method, such as NSArray/NSDictionary/etc. Use of Foundation collections in Swift code is pretty rare, but just in case, the rule is disabled by default.

  • If a file begins with a comment, the stripHeaders rule will remove it if it is followed by a blank line. To avoid this, make sure that the first comment is directly followed by a line of code.

  • When running a version of SwiftFormat built using Xcode 10.2 on macOS 10.14.3 or earlier, you may experience a crash with the error "dyld: Library not loaded: @rpath/libswiftCore.dylib". To fix this, you need to install the Swift 5 Runtime Support for Command Line Tools. These tools are included by default in macOS 10.14.4 and later.

Tip Jar

SwiftFormat is not a commercially-funded product, it's a labor of love given freely to the community. If you find it useful, please consider making a donation.

Donate via PayPal

Credits

(Full list of contributors)

Comments
  • "Failed to format any files" on second run with --config option

    Adding this on the build phase: ${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" "$SRCROOT" ' --config ' "$SRCROOT/../swiftformart"

    fails on the second run: Failed to format any files.

    Adding this: ``${PODS_ROOT}/SwiftFormat/CommandLineTool/swiftformat" "$SRCROOT" `

    Works fine all the times.

    version:

    • SwiftFormat/CLI (0.44.6)
    bug info needed 
    opened by brunofgs 25
  • Using globs in config file significantly slows down SwiftFormat

    Using globs in config file significantly slows down SwiftFormat

    It's the first time I'm trying to use the globs added in https://github.com/nicklockwood/SwiftFormat/issues/301.

    After I add a simple *SwiftGen* glob, I notice that it significantly slows down swiftformat run time.

    For the same number of files (116 in this example),

    • Running swiftformat with globs in config: 11.69s
    • Running swiftformat without any globs in config: 0.69s

    There's almost 20 times increase in execution time.

    Not sure if processing globs should really slow down the execution. On the opposite, since with globs more files are ignored, it should run even faster.

    Using swiftformat in git commit hooks or in Xcode build phase will add this extra delay. I've noticed that the more globs there are in config, the longer it takes.

    Looks like options parsing code in CommandLine.swift is slow when it comes to using expandGlobs. I've never used this API, so I'm not quite sure why is it slow and if it can be improved to be faster.

    opened by mgrebenets 22
  • Use project-specific configuration in Xcode extension

    Use project-specific configuration in Xcode extension

    Related: #1108

    Happy new year.

    I added a new target EditorExtensionXPCService to call AppleScript to get the folder path of the current opening project.

    It then searches upwards for a .swiftformat file, parses it, and sends it back to the extension. If the file is not found, we can fall back to using the in-app configuration.

    One small issue is that AppleScripts may take 3-4 seconds to compile (or maybe warm-up?) after we run a command on the extension. But luckily, it only happens once until Xcode is quit and relaunched.

    opened by intitni 18
  • Trailing closure indentation issue

    Trailing closure indentation issue

    Hi!

    I'm curious if it's an issue or intended behavior, but when I run SwiftFormat on that code:

    UIView.animate(withDuration: duration,
                   options: .allowUserInteraction) {
        presentingView?.frame = finalFrame
    } completion: { _ in
        transitionContext.completeTransition(true)
    }
    

    It is formatted to:

    UIView.animate(withDuration: duration,
                   options: .allowUserInteraction) {
            presentingView?.frame = finalFrame
    } completion: { _ in
        transitionContext.completeTransition(true)
    }
    

    Any feedback will be appreciated!

    bug fixed in develop 
    opened by jakubkiermasz-zd 18
  • SwiftFormat crashes on launch due to invalid signature

    SwiftFormat crashes on launch due to invalid signature

    Podfile contains pod 'SwiftFormat/CLI'

    We run a CI job every Sunday to auto-format our code with SwiftFormat. It passed on Dec 23, 2018 12:32 AM but failed on next run at Dec 30, 2018 12:32 AM. The executable just crashes instantly on launch. I can repro locally on my MBP with 10.14.2 (18C54).

    Version 0.35.6 and 0.37.1 are affected (I just tried running pod update as we were using an old version of SwiftFormat).

    $ ./Pods/SwiftFormat/CommandLineTool/swiftformat
    Killed: 9
    
    $ lldb ./Pods/SwiftFormat/CommandLineTool/swiftformat
    (lldb) target create "./Pods/SwiftFormat/CommandLineTool/swiftformat"
    Current executable set to './Pods/SwiftFormat/CommandLineTool/swiftformat' (x86_64).
    (lldb) r
    error: process exited with status -1 (unable to attach)
    

    Crash logs are created in ~/Library/Logs/DiagnosticReports:

    Process:               swiftformat [25065]
    Path:                  /Users/USER/*/swiftformat
    Identifier:            swiftformat
    Version:               ???
    Code Type:             X86-64 (Native)
    Parent Process:        bash [9970]
    Responsible:           swiftformat [25065]
    User ID:               501
    
    Date/Time:             2018-12-30 14:28:21.830 -0800
    OS Version:            Mac OS X 10.14.2 (18C54)
    Report Version:        12
    Bridge OS Version:     3.0 (14Y674)
    Anonymous UUID:        8618749C-55BE-49B0-D91A-6F09D9DE37EE
    
    Sleep/Wake UUID:       98FD6B43-A7EA-4AF3-AFC3-F7BE3FEA5A2B
    
    Time Awake Since Boot: 23000 seconds
    Time Since Wake:       1900 seconds
    
    System Integrity Protection: enabled
    
    Crashed Thread:        Unknown
    
    Exception Type:        EXC_CRASH (Code Signature Invalid)
    Exception Codes:       0x0000000000000000, 0x0000000000000000
    Exception Note:        EXC_CORPSE_NOTIFY
    
    Termination Reason:    Namespace CODESIGNING, Code 0x1
    
    kernel messages:
    
    Backtrace not available
    
    Unknown thread crashed with X86 Thread State (64-bit):
      rax: 0x0000000000000000  rbx: 0x0000000000000000  rcx: 0x0000000000000000  rdx: 0x0000000000000000
      rdi: 0x0000000000000000  rsi: 0x0000000000000000  rbp: 0x0000000000000000  rsp: 0x00007ffee37faa30
       r8: 0x0000000000000000   r9: 0x0000000000000000  r10: 0x0000000000000000  r11: 0x0000000000000000
      r12: 0x0000000000000000  r13: 0x0000000000000000  r14: 0x0000000000000000  r15: 0x0000000000000000
      rip: 0x0000000112eb7000  rfl: 0x0000000000000200  cr2: 0x0000000000000000
      
    Logical CPU:     0
    Error Code:      0x00000000
    Trap Number:     0
    
    
    Binary images description not available
    
    
    External Modification Summary:
      Calls made by other processes targeting this process:
        task_for_pid: 0
        thread_create: 0
        thread_set_state: 0
      Calls made by this process:
        task_for_pid: 0
        thread_create: 0
        thread_set_state: 0
      Calls made by all processes on this machine:
        task_for_pid: 17217
        thread_create: 0
        thread_set_state: 0
    

    Here's the code-signing info:

    $ codesign -dvvv ./Pods/SwiftFormat/CommandLineTool/swiftformat 
    Executable=/Users/pol/Source/ios_client/Pods/SwiftFormat/CommandLineTool/swiftformat
    Identifier=swiftformat
    Format=Mach-O thin (x86_64)
    CodeDirectory v=20200 size=87691 flags=0x0(none) hashes=2733+5 location=embedded
    Hash type=sha256 size=32
    CandidateCDHash sha1=253b388fb4856a62c5e8cbfa17f148b5d5bb481b
    CandidateCDHash sha256=0f90651f795ac74b5f3a0baf853b092ea8b2c71a
    Hash choices=sha1,sha256
    CDHash=0f90651f795ac74b5f3a0baf853b092ea8b2c71a
    Signature size=4778
    Authority=(unavailable)
    Info.plist=not bound
    TeamIdentifier=8VQKF583ED
    Sealed Resources=none
    Internal requirements count=1 size=172
    
    opened by swisspol 18
  • Command line tool fails to compile/run: dyld not found in

    Command line tool fails to compile/run: dyld not found in "formatCode" build phase, image not found

    I have checked out the latest tag 0.40.5. I tried to compile the target SwiftFormat (Command line tools) but it fails. It looks like there is an issue in the formatCode phase of the build. The command "${SRCROOT}/format.sh" fails with: dyld: Library not loaded: @rpath/libswiftCore.dylib Referenced from: /Users/i040023/com.sap.mobile.platform.client.oss.ios.swiftformat/src/CommandLineTool/swiftformat Reason: image not found /Users/i040023/com.sap.mobile.platform.client.oss.ios.swiftformat/src/format.sh: line 3: 4077 Abort trap: 6 CommandLineTool/swiftformat . --cache ignore Command PhaseScriptExecution failed with a nonzero exit code

    Xcode is 10.2 os: 10.14.3

    opened by bgalamb 16
  • Removing necessary explicit reference to self in autoclosures.

    Removing necessary explicit reference to self in autoclosures.

    I've got some regular ol' XCTestCases using matchers from Nimble. The Nimble expect function uses an autoclosure to get its expect(foo) == bar style matchers. However, with the redundant self option on, SwiftFormat doesn't seem to realize that the reference to self is necessary to make the capture semantics explicit and removes it, resulting in code that no longer compiles.

    In other words

    class FooTests: XCTestCase {
        let foo = 1
    
        func testFoo() {
            expect(self.foo) == 1
        }
    }
    

    turns into

    class FooTests: XCTestCase {
        let foo = 1
    
        func testFoo() {
            expect(foo) == 1
        }
    }
    

    Which results in the error Reference to property 'foo' in closure requires explicit 'self.' to make capture semantics explicit.

    opened by jarsen 16
  • exclude option from config file is ignored when run for single file with githook

    exclude option from config file is ignored when run for single file with githook

    That's the issue we faced recently.

    We have configuration file with exclude option:

    --exclude **/Generated
    

    If you run swiftformat for root folder like that:

    swiftformat . --config swiftformat.config
    

    files in Generated folder will be ignored correctly.

    But, if you run it for specific file, like we do in githook for all staged files:

    swiftformat --config swiftformat.config "SomeFolder/Generated/SomeFile.swift"
    

    This file will be formatted.

    After investigation we found that issue was introduced in version 0.36.0. Version 0.35.10 will say error: no eligible files found at .../SomeFolder/Generated/SomeFile.swift but will not format this file.

    @nicklockwood please, review that change, probably it's the reason https://github.com/nicklockwood/SwiftFormat/commit/10cafc4af83b596dbf7ee932d421d68b15006e5e

    bug fixed in develop 
    opened by NKorchagin 15
  • How do I use decimalgrouping?

    How do I use decimalgrouping?

    When I have this in my .swiftformat file:

    --enable isEmpty
    --enable wrapSwitchCases
    --enable wrapEnumCases
    --disable wrapMultilineStatementBraces
    --maxwidth 80
    --wraparguments before-first
    --wrapparameters before-first
    --wrapcollections before-first
    --wrapconditions before-first
    --decimalgrouping 3,4
    

    it just ignores the --decimalgrouping 3,4. It doesn't format 1000 to 1_000.

    When I run this in my command line:

    swiftformat --rules numberFormatting --decimalgrouping 3,4 .

    it will do the formatting.

    To me it is unclear how I should apply the decimalgrouping through a .swiftformat file. It looks like it is some sort of sub rule of numberFormatting, but the documentation doesn't state how I should apply it in my .swiftformat file.

    When I change my .swiftformat file like so, I get an error:

    --enable isEmpty
    --enable wrapSwitchCases
    --enable wrapEnumCases
    --disable wrapMultilineStatementBraces
    --maxwidth 80
    --wraparguments before-first
    --wrapparameters before-first
    --wrapcollections before-first
    --wrapconditions before-first
    numberFormatting --decimalgrouping 3,4
    

    error: Unknown option 'numberFormatting' in configuration file.

    opened by Jasperav 14
  • Technical/wrap options

    Technical/wrap options

    Hi 👋,

    as agreed I've tried to implement --conditionswrap. I hope that I got your idea in the right way 😅 At least this option does what I'd expect.

    Looking forward to hearing from you.

    best, Alex.

    opened by Parabak 14
  • Running pre-commit hook from Xcode

    Running pre-commit hook from Xcode

    When trying to commit from Xcode, pre-commit tries to run swiftformat from the repo but fails to commit.

    Xcode warning message after commit:

    The working copy “Testing” failed to commit files.
    Running SwiftFormat...\n
    SwiftFormat completed in 0.13s.
    1/1 files formatted.
    

    In the Xcode 11.5, it seems as the changes were formatted and committed but in the terminal it looks like the changes where committed and then formatted resulting in unstaged changes.

    pre-commit hook

    git diff --diff-filter=d --staged --name-only | grep -e '\(.*\).swift$' | while read line; do $PWD/swiftformat "${line}"; git add "$line"; done

    bug fixed in develop 
    opened by Milos 14
  • fix: Sort comments when sorting switch cases

    fix: Sort comments when sorting switch cases

    What?

    This has been broken for a while. Finally, I got some time to work on it.

    When sorting switch cases, the comments are not sorted. I've followed the parseImports approach to parse the switch cases in case we want to use this in other places.

    I've tried to enable it by default, but I keep getting an assert error for redundantSelf #line: 3728 that I am not sure how to fix (nor to debug). The failure message isn't that descriptive. I might need a hand @nicklockwood '

    • Is there a quick way to identify which version is causing the issue and run only that one?

    Let me know what you think.

    UPDATE

    Seems to fail on the regression suite. Expression.swiftor file seemSprinter.swift to be causing problems (among others).

    opened by facumenzella 0
  • "semicolons" rule removing a semicolon which affects the behavior of the code

    Hi ! I use TCA's dependency management mechanism, which is detailed here.

    Essentially, it consists in using the expresion @Dependency(\.myDependency) var myDependency where needed, after which myDependency will be injected and can be used.

    While it is primarily meant to be used as properties in struct and class declarations, I've recently come to use it in func bodies and in closures, which led to the following code:

    struct ApiClient {
        static func live() -> Self {
            authenticate: { loginOption in
                await session.authenticate(with: loginOption)
                    .mapError { error in
                        @Dependency(\.crashAnalyticsClient) var crashClient;
                        crashClient.track(error)
                        return error
                    }
            }
        }
    }
    

    The ; at the end of the dependency injection declaration is necessary, otherwise the Swift compiler panics and interprets the line that follows as the same expression (ie, as: @Dependency(\.crashAnalyticsClient) var crashClient crashClient.track(error), which causes a compilation error.

    However, when running swiftformat . --swiftversion 5, the semicolon is removed, leading to a compilation error. As per the semicolon rule, "semicolon is not removed if it would affect the behavior of the code".

    I'm not sure whether the semicolon should be necessary here, reporting just in case.

    opened by louis-prudhomme 0
  • Config file as a remote url

    Config file as a remote url

    Hi,

    I know the SwiftFormat app can't use the config file, I assume this is due to sandboxing.

    However, could the config file accept a parent remote url...

    Also the app accept a remote url config?

    Granted these's shouldn't be refreshed that often.

    But this would solve some big issues of me

    I'd love to hear your thoughts @nicklockwood

    Best regards,

    Jules.

    opened by JulesMoorhouse 0
  • The closing indent of closure has changed from 0.50.7.

    The closing indent of closure has changed from 0.50.7.

    I have the following code:

    import UIKit
    
    UIView.animateKeyframes(withDuration: 0.2, delay: 0, options: [], animations: {
        UIView.addKeyframe(withRelativeStartTime: 0,
                           relativeDuration: 0.1, animations: {
                               // ...
                           })
    }) // <--- here
    

    When I run swiftformat 0.50.7:

    import UIKit
    
    UIView.animateKeyframes(withDuration: 0.2, delay: 0, options: [], animations: {
        UIView.addKeyframe(withRelativeStartTime: 0,
                           relativeDuration: 0.1, animations: {
                               // ...
                           })
        }) // <--- here
    

    This is undesirable. If this is a bug, I would like to see it reverted.

    opened by bookii 1
Releases(0.50.7)
Owner
Nick Lockwood
Nick Lockwood
Measure Swift code metrics and get reports in Xcode, Jenkins and other CI platforms.

Taylor ⚠️ Taylor is DEPRECATED. Use SwiftLint instead. A tool aimed to increase Swift code quality, by checking for conformance to code metrics. Taylo

YOPESO 301 Dec 24, 2022
A static source code analysis tool to improve quality and reduce defects for C, C++ and Objective-C

OCLint - https://oclint.org OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code

The OCLint Static Code Analysis Tool 3.6k Dec 29, 2022
An Xcode formatter plug-in to format your swift code.

Swimat Swimat is an Xcode plug-in to format your Swift code. Preview Installation There are three way to install. Install via homebrew-cask # Homebrew

Jintin 1.6k Jan 7, 2023
Swift-lint-plugin - A SwiftPM plugin that adds a linting command

SwiftLintPlugin This is a SwiftPM plugin that adds a lint command. SwiftPM plugi

null 9 Nov 23, 2022
A tool to enforce Swift style and conventions.

SwiftLint A tool to enforce Swift style and conventions, loosely based on the now archived GitHub Swift Style Guide. SwiftLint enforces the style guid

Realm 16.9k Jan 9, 2023
Simple iOS app blackbox assessment tool. Powered by frida.re and vuejs.

Discontinued Project This project has been discontinued. Please use the new Grapefruit #74 frida@14 compatibility issues frida@14 introduces lots of b

Chaitin Tech 1.6k Dec 16, 2022
A linter tool for Interface Builder

IBLinter A linter tool to normalize .xib and .storyboard files. Inspired by realm/SwiftLint Installation Using Homebrew $ brew install iblinter Using

IBDecodable 945 Nov 11, 2022
iOS tool that helps with profiling iOS Memory usage.

FBMemoryProfiler An iOS library providing developer tools for browsing objects in memory over time, using FBAllocationTracker and FBRetainCycleDetecto

Facebook Archive 3.4k Dec 7, 2022
An xcconfig (Xcode configuration) file for easily turning on a boatload of warnings in your project or its targets.

Warnings This is an xcconfig file to make it easy for you to turn on a large suite of useful warnings in your Xcode project. These warnings catch bugs

Peter Hosey 438 Nov 8, 2022
SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations.

SwiftCop is a validation library fully written in Swift and inspired by the clarity of Ruby On Rails Active Record validations. Objective Build a stan

Andres Canal 542 Sep 17, 2022
Cross-platform static analyzer and linter for Swift.

Wiki • Installation • Usage • Features • Developers • License Tailor is a cross-platform static analysis and lint tool for source code written in Appl

Sleekbyte 1.4k Dec 19, 2022
Type-safe observable values and collections in Swift

GlueKit ⚠️ WARNING ⚠️ This project is in a prerelease state. There is active work going on that will result in API changes that can/will break code wh

null 361 Oct 12, 2022
Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing projects.

Trackable Trackable is a simple analytics integration helper library. It’s especially designed for easy and comfortable integration with existing proj

Vojta Stavik 145 Apr 14, 2022
Makes it easier to support older versions of iOS by fixing things and adding missing methods

PSTModernizer PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set

PSPDFKit Labs 217 Aug 9, 2022
Find common xib and storyboard-related problems without running your app or writing unit tests.

IBAnalyzer Find common xib and storyboard-related problems without running your app or writing unit tests. Usage Pass a path to your project to ibanal

Arek Holko 955 Oct 15, 2022
Skredvarsel app - an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Skredvarsel (Avalanche warning) app is an iOS, iPadOS, and macOS application that provides daily avalanche warnings from the Norwegian Avalanche Warning Service API

Jonas Follesø 8 Dec 15, 2022
Exclude files and folders from Alfred’s search results

Ignore in Alfred Alfred Workflow Exclude files and folders from Alfred’s search results ⤓ Download Workflow About The macOS metadata search API only a

Alfred 10 Dec 13, 2022
Lint anything by combining the power of Swift & regular expressions.

Installation • Getting Started • Configuration • Xcode Build Script • Donation • Issues • Regex Cheat Sheet • License AnyLint Lint any project in any

Flinesoft 116 Sep 24, 2022
💊 Syntactic sugar for Swift do-try-catch

Fallback Syntactic sugar for Swift do-try-catch. At a Glance value = try fallback( try get("A"), try get("B"), try get("C"), try get("D") ) is

Suyeol Jeon 43 May 25, 2020