mirror of
https://github.com/nicklockwood/SwiftFormat.git
synced 2026-05-17 10:30:35 +00:00
169 lines
5.4 KiB
Swift
169 lines
5.4 KiB
Swift
//
|
|
// FileHeader.swift
|
|
// SwiftFormat
|
|
//
|
|
// Created by Nick Lockwood on 3/7/17.
|
|
// Copyright © 2024 Nick Lockwood. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
public extension FormatRule {
|
|
/// Strip header comments from the file
|
|
static let fileHeader = FormatRule(
|
|
help: "Use specified source file header template for all files.",
|
|
runOnceOnly: true,
|
|
options: ["header", "date-format", "timezone"],
|
|
sharedOptions: ["linebreaks"]
|
|
) { formatter in
|
|
var headerTokens = [Token]()
|
|
var directives = [String]()
|
|
switch formatter.options.fileHeader {
|
|
case .ignore:
|
|
return
|
|
case var .replace(string):
|
|
let file = formatter.options.fileInfo
|
|
let options = ReplacementOptions(
|
|
dateFormat: formatter.options.dateFormat,
|
|
timeZone: formatter.options.timeZone
|
|
)
|
|
|
|
for (key, replacement) in formatter.options.fileInfo.replacements {
|
|
if let replacementStr = replacement.resolve(file, options) {
|
|
while let range = string.range(of: "{\(key.rawValue)}") {
|
|
string.replaceSubrange(range, with: replacementStr)
|
|
}
|
|
}
|
|
}
|
|
headerTokens = tokenize(string)
|
|
directives = headerTokens.compactMap {
|
|
guard case let .commentBody(body) = $0 else {
|
|
return nil
|
|
}
|
|
return body.commentDirective
|
|
}
|
|
}
|
|
|
|
guard let headerRange = formatter.headerCommentTokenRange(includingDirectives: directives) else {
|
|
return
|
|
}
|
|
|
|
if headerTokens.isEmpty {
|
|
formatter.removeTokens(in: headerRange)
|
|
return
|
|
}
|
|
|
|
var lastHeaderTokenIndex = headerRange.endIndex - 1
|
|
let endIndex = lastHeaderTokenIndex + headerTokens.count
|
|
if formatter.tokens.endIndex > endIndex, headerTokens == Array(formatter.tokens[
|
|
lastHeaderTokenIndex + 1 ... endIndex
|
|
]) {
|
|
lastHeaderTokenIndex += headerTokens.count
|
|
}
|
|
let headerLinebreaks = headerTokens.reduce(0) { result, token -> Int in
|
|
result + (token.isLinebreak ? 1 : 0)
|
|
}
|
|
if lastHeaderTokenIndex < formatter.tokens.count - 1 {
|
|
headerTokens.append(.linebreak(formatter.options.linebreak, headerLinebreaks + 1))
|
|
if lastHeaderTokenIndex < formatter.tokens.count - 2,
|
|
!formatter.tokens[lastHeaderTokenIndex + 1 ... lastHeaderTokenIndex + 2].allSatisfy(\.isLinebreak)
|
|
{
|
|
headerTokens.append(.linebreak(formatter.options.linebreak, headerLinebreaks + 2))
|
|
}
|
|
}
|
|
if let index = formatter.index(of: .nonSpace, after: lastHeaderTokenIndex, if: {
|
|
$0.isLinebreak
|
|
}) {
|
|
lastHeaderTokenIndex = index
|
|
}
|
|
formatter.replaceTokens(in: headerRange.startIndex ..< lastHeaderTokenIndex + 1, with: headerTokens)
|
|
} examples: {
|
|
"""
|
|
You can use the following tokens in the text:
|
|
|
|
Token | Description
|
|
--- | ---
|
|
`{file}` | File name
|
|
`{year}` | Current year
|
|
`{created}` | File creation date
|
|
`{created.year}` | File creation year
|
|
`{author}` | Name and email of the user who first committed the file
|
|
`{author.name}` | Name of the user who first committed the file
|
|
`{author.email}` | Email of the user who first committed the file
|
|
|
|
**Example**:
|
|
|
|
`--header \\n {file}\\n\\n Copyright © {created.year} {author.name}.\\n`
|
|
|
|
```diff
|
|
- // SomeFile.swift
|
|
|
|
+ //
|
|
+ // SomeFile.swift
|
|
+ // Copyright © 2023 Tim Apple.
|
|
+ //
|
|
```
|
|
|
|
You can use the following built-in formats for `--date-format`:
|
|
|
|
Token | Description
|
|
--- | ---
|
|
system | Use the local system locale
|
|
iso | ISO 8601 (yyyy-MM-dd)
|
|
dmy | Date/Month/Year (dd/MM/yyyy)
|
|
mdy | Month/Day/Year (MM/dd/yyyy)
|
|
|
|
Custom formats are defined using
|
|
[Unicode symbols](https://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Field_Symbol_Table).
|
|
|
|
`--date-format iso`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 2023-08-10
|
|
```
|
|
|
|
`--date-format dmy`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 10/08/2023
|
|
```
|
|
|
|
`--date-format mdy`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 08/10/2023
|
|
```
|
|
|
|
`--date-format 'yyyy.MM.dd.HH.mm'`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 2023.08.10.11.00
|
|
```
|
|
|
|
Setting a time zone enforces consistent date formatting across environments
|
|
around the world. By default the local system locale is used and for convenience
|
|
`gmt` and `utc` can be used. The time zone can be further customized by
|
|
setting it to a abbreviation/time zone identifier supported by the Swift
|
|
standard library.
|
|
|
|
`--date-format 'yyyy-MM-dd HH:mm ZZZZ' --timezone utc`
|
|
|
|
```diff
|
|
- // Created {created}
|
|
+ // Created 2023-08-10 11:00 GMT
|
|
```
|
|
|
|
`--date-format 'yyyy-MM-dd HH:mm ZZZZ' --timezone Pacific/Fiji`
|
|
|
|
```diff
|
|
- // Created 2023-08-10 11:00 GMT
|
|
+ // Created 2023-08-10 23:00 GMT+12:00
|
|
```
|
|
"""
|
|
}
|
|
}
|