@@ -8,6 +8,61 @@ extension String {
8
8
public var sentenceCased : String {
9
9
return String ( characters. prefix ( 1 ) ) . uppercased ( ) + String( characters. dropFirst ( ) )
10
10
}
11
+
12
+ /**
13
+ Replaces `{tokens}` in the receiver using the given closure.
14
+ */
15
+ public func replacingTokens( using interpolator: ( ( TokenType ) -> String ) ) -> String {
16
+ let scanner = Scanner ( string: self )
17
+ scanner. charactersToBeSkipped = nil
18
+ var result = " "
19
+ while !scanner. isAtEnd {
20
+ var buffer : NSString ?
21
+
22
+ if scanner. scanUpTo ( " { " , into: & buffer) {
23
+ result += buffer! as String
24
+ }
25
+ guard scanner. scanString ( " { " , into: nil ) else {
26
+ continue
27
+ }
28
+
29
+ var token : NSString ?
30
+ guard scanner. scanUpTo ( " } " , into: & token) else {
31
+ continue
32
+ }
33
+
34
+ if scanner. scanString ( " } " , into: nil ) {
35
+ if let tokenType = TokenType ( description: token! as String ) {
36
+ result += interpolator ( tokenType)
37
+ }
38
+ } else {
39
+ result += token! as String
40
+ }
41
+ }
42
+
43
+ // remove excess spaces
44
+ result = result. replacingOccurrences ( of: " \\ s \\ s " , with: " " , options: . regularExpression)
45
+
46
+ // capitalize
47
+ let meta = OSRMTextInstructionsStrings [ " meta " ] as! [ String : Any ]
48
+ if meta [ " capitalizeFirstLetter " ] as? Bool ?? false {
49
+ result = result. sentenceCased
50
+ }
51
+ return result
52
+ }
53
+ }
54
+
55
+ public enum Phrase : String {
56
+ case linkedInstructionsWithDistance = " two linked by distance "
57
+ case linkedInstructions = " two linked "
58
+ case instructionWithDistance = " one in distance "
59
+ case nameWithRef = " name and ref "
60
+ }
61
+
62
+ public struct PhraseOption {
63
+ static let firstInstruction = " instruction_one "
64
+ static let secondInstruction = " instruction_two "
65
+ static let distance = " distance "
11
66
}
12
67
13
68
public class OSRMInstructionFormatter : Formatter {
@@ -254,58 +309,27 @@ public class OSRMInstructionFormatter: Formatter {
254
309
if step. finalHeading != nil { bearing = Int ( step. finalHeading! as Double ) }
255
310
256
311
// Replace tokens
257
- let scanner = Scanner ( string: instruction)
258
- scanner. charactersToBeSkipped = nil
259
- var result = " "
260
- while !scanner. isAtEnd {
261
- var buffer : NSString ?
262
-
263
- if scanner. scanUpTo ( " { " , into: & buffer) {
264
- result += buffer! as String
265
- }
266
- guard scanner. scanString ( " { " , into: nil ) else {
267
- continue
268
- }
269
-
270
- var token : NSString ?
271
- guard scanner. scanUpTo ( " } " , into: & token) else {
272
- continue
312
+ let result = instruction. replacingTokens { ( tokenType) -> String in
313
+ var replacement : String
314
+ switch tokenType {
315
+ case . code: replacement = step. codes? . first ?? " "
316
+ case . wayName: replacement = wayName
317
+ case . destination: replacement = destination
318
+ case . exitCode: replacement = exitCode
319
+ case . exitIndex: replacement = exitOrdinal
320
+ case . rotaryName: replacement = rotaryName
321
+ case . laneInstruction: replacement = laneInstruction ?? " "
322
+ case . modifier: replacement = modifierConstant
323
+ case . direction: replacement = directionFromDegree ( degree: bearing)
324
+ case . wayPoint: replacement = nthWaypoint ?? " "
325
+ case . firstInstruction, . secondInstruction, . distance:
326
+ fatalError ( " Unexpected token type \( tokenType) in individual instruction " )
273
327
}
274
-
275
- if scanner. scanString ( " } " , into: nil ) {
276
- if let tokenType = TokenType ( description: token! as String ) {
277
- var replacement : String
278
- switch tokenType {
279
- case . code: replacement = step. codes? . first ?? " "
280
- case . wayName: replacement = wayName
281
- case . destination: replacement = destination
282
- case . exitCode: replacement = exitCode
283
- case . exitIndex: replacement = exitOrdinal
284
- case . rotaryName: replacement = rotaryName
285
- case . laneInstruction: replacement = laneInstruction ?? " "
286
- case . modifier: replacement = modifierConstant
287
- case . direction: replacement = directionFromDegree ( degree: bearing)
288
- case . wayPoint: replacement = nthWaypoint ?? " "
289
- }
290
- if tokenType == . wayName {
291
- result += replacement // already modified above
292
- } else {
293
- result += modifyValueByKey ? ( tokenType, replacement) ?? replacement
294
- }
295
- }
328
+ if tokenType == . wayName {
329
+ return replacement // already modified above
296
330
} else {
297
- result += token! as String
331
+ return modifyValueByKey ? ( tokenType , replacement ) ?? replacement
298
332
}
299
-
300
- }
301
-
302
- // remove excess spaces
303
- result = result. replacingOccurrences ( of: " \\ s \\ s " , with: " " , options: . regularExpression)
304
-
305
- // capitalize
306
- let meta = OSRMTextInstructionsStrings [ " meta " ] as! [ String : Any ]
307
- if meta [ " capitalizeFirstLetter " ] as? Bool ?? false {
308
- result = result. sentenceCased
309
333
}
310
334
311
335
return result
0 commit comments