@@ -8,6 +8,48 @@ 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
+ }
11
53
}
12
54
13
55
public class OSRMInstructionFormatter : Formatter {
@@ -192,7 +234,18 @@ public class OSRMInstructionFormatter: Formatter {
192
234
let isMotorway = roadClasses? . contains ( . motorway) ?? false
193
235
194
236
if let name = name, let ref = ref, name != ref, !isMotorway {
195
- wayName = modifyValueByKey != nil ? " \( modifyValueByKey!( . wayName, name) ) ( \( modifyValueByKey!( . code, ref) ) ) " : " \( name) ( \( ref) ) "
237
+ let phrases = instructions [ " phrase " ] as! [ String : String ]
238
+ let phrase = phrases [ " name and ref " ] !
239
+ wayName = phrase. replacingTokens ( using: { ( tokenType) -> String in
240
+ switch tokenType {
241
+ case . wayName:
242
+ return modifyValueByKey ? ( . wayName, name) ?? name
243
+ case . code:
244
+ return modifyValueByKey ? ( . code, ref) ?? ref
245
+ default :
246
+ fatalError ( " Unexpected token type \( tokenType) in name-and-ref phrase " )
247
+ }
248
+ } )
196
249
} else if let ref = ref, isMotorway, let decimalRange = ref. rangeOfCharacter ( from: . decimalDigits) , !decimalRange. isEmpty {
197
250
wayName = modifyValueByKey != nil ? " \( modifyValueByKey!( . code, ref) ) " : ref
198
251
} else if name == nil , let ref = ref {
@@ -254,58 +307,27 @@ public class OSRMInstructionFormatter: Formatter {
254
307
if step. finalHeading != nil { bearing = Int ( step. finalHeading! as Double ) }
255
308
256
309
// 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
310
+ let result = instruction. replacingTokens { ( tokenType) -> String in
311
+ var replacement : String
312
+ switch tokenType {
313
+ case . code: replacement = step. codes? . first ?? " "
314
+ case . wayName: replacement = wayName
315
+ case . destination: replacement = destination
316
+ case . exitCode: replacement = exitCode
317
+ case . exitIndex: replacement = exitOrdinal
318
+ case . rotaryName: replacement = rotaryName
319
+ case . laneInstruction: replacement = laneInstruction ?? " "
320
+ case . modifier: replacement = modifierConstant
321
+ case . direction: replacement = directionFromDegree ( degree: bearing)
322
+ case . wayPoint: replacement = nthWaypoint ?? " "
323
+ case . firstInstruction, . secondInstruction, . distance:
324
+ fatalError ( " Unexpected token type \( tokenType) in individual instruction " )
273
325
}
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
- }
326
+ if tokenType == . wayName {
327
+ return replacement // already modified above
296
328
} else {
297
- result += token! as String
329
+ return modifyValueByKey ? ( tokenType , replacement ) ?? replacement
298
330
}
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
331
}
310
332
311
333
return result
0 commit comments