Skip to content

Commit 2c463bb

Browse files
committed
trim empty leading lines from the first subslice of a snippet slice
1 parent a9fafbb commit 2c463bb

File tree

2 files changed

+87
-26
lines changed

2 files changed

+87
-26
lines changed

Sources/MarkdownPluginSwift/Snippets/SnippetParser.SliceBounds.swift

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,48 @@ extension SnippetParser.SliceBounds
2424
{
2525
// We need to do two passes over the source ranges, as indentation is computed across
2626
// the entire slice, and not just one subslice.
27+
var trimEmptyLines:Bool = true
2728
let ranges:[Range<Int>] = self.ranges.compactMap
2829
{
29-
let start:Int = $0.lowerBound.utf8Offset
30+
var start:Int = $0.lowerBound.utf8Offset
3031
if start >= utf8.endIndex
3132
{
3233
// This could happen if the file ends with a control comment and no
3334
// final newline.
3435
return nil
3536
}
3637

38+
// We need to roll forward through any whitespace-only lines. This is difficult
39+
// to do at the syntax level, because we traditionally associate trailing trivia
40+
// with the token that comes after the slice markers. So we do it here.
41+
//
42+
// This should only be done for the first range, to preserve the ability to insert
43+
// empty lines between subslices.
44+
if trimEmptyLines
45+
{
46+
trimming:
47+
while true
48+
{
49+
for (i, byte):(Int, UInt8) in zip(start..., utf8[start...])
50+
{
51+
switch byte
52+
{
53+
// '\r', '\t', ' '
54+
case 0x0D, 0x09, 0x20:
55+
continue
56+
57+
// '\n'
58+
case 0x0A:
59+
start = utf8.index(after: i)
60+
continue trimming
61+
62+
default:
63+
break trimming
64+
}
65+
}
66+
}
67+
}
68+
3769
let end:Int = min($0.upperBound.utf8Offset, utf8.endIndex)
3870
if end <= start
3971
{
@@ -42,6 +74,7 @@ extension SnippetParser.SliceBounds
4274
}
4375
else
4476
{
77+
trimEmptyLines = false
4578
return start ..< end
4679
}
4780
}

Sources/MarkdownPluginSwiftTests/Main.Snippets.swift

Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -88,28 +88,6 @@ extension Main.Snippets:TestBattery
8888
8989
""")
9090
}
91-
if let tests:TestGroup = tests / "CollapseWhitespace"
92-
{
93-
Self.run(tests: tests,
94-
snippet:
95-
"""
96-
/// Here’s how to say ‘hi’ to Barbie.
97-
98-
99-
100-
print("Hi Barbie!")
101-
102-
""",
103-
caption:
104-
"""
105-
Here’s how to say ‘hi’ to Barbie.
106-
""",
107-
slices:
108-
"""
109-
print("Hi Barbie!")
110-
111-
""")
112-
}
11391
if let tests:TestGroup = tests / "TriviaOnly"
11492
{
11593
Self.run(tests: tests,
@@ -135,13 +113,17 @@ extension Main.Snippets:TestBattery
135113
Self.run(tests: tests,
136114
snippet:
137115
"""
138-
/// Here’s how to say ‘hi’ to Barbie.
116+
/// Here’s how to say ‘hi’ to Barbie and Skipper.
139117
140118
// snippet.HI_BARBIE
141119
142120
// print("Hi Barbie!")
143121
122+
// snippet.hide
144123
124+
// snippet.show
125+
126+
// print("Hi Skipper!")
145127
146128
// snippet.end
147129
@@ -150,11 +132,12 @@ extension Main.Snippets:TestBattery
150132
"""
151133
Here’s how to say ‘hi’ to Barbie.
152134
""",
153-
slices:
135+
slices: // This should preserve the empty line before `Hi Skipper!`.
154136
"""
155-
156137
// print("Hi Barbie!")
157138
139+
// print("Hi Skipper!")
140+
158141
""")
159142
}
160143
if let tests:TestGroup = tests / "Indented"
@@ -274,6 +257,51 @@ extension Main.Snippets:TestBattery
274257
275258
""")
276259
}
260+
if let tests:TestGroup = tests / "AnonymousCollapseWhitespace"
261+
{
262+
Self.run(tests: tests,
263+
snippet:
264+
"""
265+
/// Here’s how to say ‘hi’ to Barbie.
266+
267+
268+
269+
print("Hi Barbie!")
270+
271+
""",
272+
caption:
273+
"""
274+
Here’s how to say ‘hi’ to Barbie.
275+
""",
276+
slices:
277+
"""
278+
print("Hi Barbie!")
279+
280+
""")
281+
}
282+
if let tests:TestGroup = tests / "NominalCollapseWhitespace"
283+
{
284+
Self.run(tests: tests,
285+
snippet:
286+
"""
287+
/// Here’s how to say ‘hi’ to Barbie.
288+
289+
290+
// snippet.BARBIE
291+
292+
print("Hi Barbie!")
293+
294+
""",
295+
caption:
296+
"""
297+
Here’s how to say ‘hi’ to Barbie.
298+
""",
299+
slices:
300+
"""
301+
print("Hi Barbie!")
302+
303+
""")
304+
}
277305
if let tests:TestGroup = tests / "Empty"
278306
{
279307
Self.run(tests: tests,

0 commit comments

Comments
 (0)