Skip to content

Commit 4aa7233

Browse files
committed
Update the command line to take an --offsets option of comma-separated "start:end" pairs (for <#297>).
1 parent 9d247cf commit 4aa7233

File tree

4 files changed

+34
-37
lines changed

4 files changed

+34
-37
lines changed

Sources/SwiftFormat/API/Selection.swift

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,13 @@ public enum Selection {
1818
case infinite
1919
case ranges([Range<AbsolutePosition>])
2020

21-
public init(json: String) {
22-
if let data = json.data(using: .utf8),
23-
let ranges = try? JSONDecoder().decode([Range<AbsolutePosition>].self, from: data) {
24-
self = .ranges(ranges)
25-
} else {
26-
self = .infinite
27-
}
28-
}
29-
30-
public init(ranges: [Range<AbsolutePosition>]) {
31-
if ranges.isEmpty {
21+
public init(offsetPairs: [Range<Int>]) {
22+
if offsetPairs.isEmpty {
3223
self = .infinite
3324
} else {
25+
let ranges = offsetPairs.map {
26+
AbsolutePosition(utf8Offset: $0.lowerBound) ..< AbsolutePosition(utf8Offset: $0.upperBound)
27+
}
3428
self = .ranges(ranges)
3529
}
3630
}
@@ -66,11 +60,3 @@ public extension Syntax {
6660
}
6761
}
6862
}
69-
70-
// FIXME: temporary until we convert argument parsing
71-
extension AbsolutePosition : Decodable {
72-
public init(from decoder: any Decoder) throws {
73-
var container = try decoder.unkeyedContainer()
74-
self.init(utf8Offset: try container.decode(Int.self))
75-
}
76-
}

Sources/_SwiftFormatTestSupport/MarkedText.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ public struct MarkedText {
2929
var text = ""
3030
var markers = [String: Int]()
3131
var lastIndex = markedText.startIndex
32-
var ranges = [Range<AbsolutePosition>]()
33-
var lastRangeStart = AbsolutePosition(utf8Offset: 0)
32+
var offsets = [Range<Int>]()
33+
var lastRangeStart = 0
3434
for marker in findMarkedRanges(in: markedText) {
3535
text += markedText[lastIndex..<marker.range.lowerBound]
3636
lastIndex = marker.range.upperBound
3737

3838
if marker.name == "" {
39-
lastRangeStart = AbsolutePosition(utf8Offset: text.utf8.count)
39+
lastRangeStart = text.utf8.count
4040
} else if marker.name == "" {
41-
ranges.append(lastRangeStart ..< AbsolutePosition(utf8Offset: text.utf8.count))
41+
offsets.append(lastRangeStart ..< text.utf8.count)
4242
} else {
4343
assert(markers[marker.name] == nil, "Marker names must be unique")
4444
markers[marker.name] = text.utf8.count
@@ -49,7 +49,7 @@ public struct MarkedText {
4949

5050
self.markers = markers
5151
self.textWithoutMarkers = text
52-
self.selection = Selection(ranges: ranges)
52+
self.selection = Selection(offsetPairs: offsets)
5353
}
5454
}
5555

Sources/swift-format/Frontend/Frontend.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,9 @@ class Frontend {
126126
}
127127

128128
var selection: Selection = .infinite
129-
if let selectionString = lintFormatOptions.selection {
130-
// TODO: do this when parsing args to catch errors?
131-
selection = Selection(json: selectionString)
129+
if let offsets = lintFormatOptions.offsets {
130+
selection = Selection(offsetPairs: offsets)
132131
}
133-
134132
let fileToProcess = FileToProcess(
135133
fileHandle: FileHandle.standardInput,
136134
url: URL(fileURLWithPath: lintFormatOptions.assumeFilename ?? "<stdin>"),
@@ -179,9 +177,8 @@ class Frontend {
179177
}
180178

181179
var selection: Selection = .infinite
182-
if let selectionString = lintFormatOptions.selection {
183-
// TODO: do this when parsing args to catch errors?
184-
selection = Selection(json: selectionString)
180+
if let offsets = lintFormatOptions.offsets {
181+
selection = Selection(offsetPairs: offsets)
185182
}
186183
return FileToProcess(
187184
fileHandle: sourceFile,

Sources/swift-format/Subcommands/LintFormatOptions.swift

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,15 @@ struct LintFormatOptions: ParsableArguments {
2626
""")
2727
var configuration: String?
2828

29-
/// A JSON string containing the selected ranges to process.
29+
/// A list of comma-separated "start:end" pairs specifying UTF-8 offsets of the ranges to format.
3030
///
3131
/// If not specified, the whole file will be formatted.
3232
@Option(
3333
name: .long,
3434
help: """
35-
A JSON string containing an array of {"offset":<Int>, "length":<Int>} pairs specifying \
36-
the source code ranges to format.
35+
A list of comma-separated "start:end" pairs specifying UTF-8 offsets of the ranges to format.
3736
""")
38-
var selection: String?
37+
var offsets: [Range<Int>]?
3938

4039

4140
/// The filename for the source code when reading from standard input, to include in diagnostic
@@ -106,8 +105,8 @@ struct LintFormatOptions: ParsableArguments {
106105
throw ValidationError("'--assume-filename' is only valid when reading from stdin")
107106
}
108107

109-
if selection != nil && paths.count > 1 {
110-
throw ValidationError("'--selection' is only valid when processing a single file")
108+
if offsets?.isEmpty == false && paths.count > 1 {
109+
throw ValidationError("'--offsets' is only valid when processing a single file")
111110
}
112111

113112
if !paths.isEmpty && !recursive {
@@ -125,3 +124,18 @@ struct LintFormatOptions: ParsableArguments {
125124
}
126125
}
127126
}
127+
128+
extension [Range<Int>] : @retroactive ExpressibleByArgument {
129+
public init?(argument: String) {
130+
let pairs = argument.components(separatedBy: ",")
131+
let ranges: [Range<Int>] = pairs.compactMap {
132+
let pair = $0.components(separatedBy: ":")
133+
if pair.count == 2, let start = Int(pair[0]), let end = Int(pair[1]), start <= end {
134+
return start ..< end
135+
} else {
136+
return nil
137+
}
138+
}
139+
self = ranges
140+
}
141+
}

0 commit comments

Comments
 (0)