@@ -8,6 +8,48 @@ extension String {
88 public var sentenceCased : String {
99 return String ( characters. prefix ( 1 ) ) . uppercased ( ) + String( characters. dropFirst ( ) )
1010 }
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+ }
1153}
1254
1355public class OSRMInstructionFormatter : Formatter {
@@ -192,7 +234,18 @@ public class OSRMInstructionFormatter: Formatter {
192234 let isMotorway = roadClasses? . contains ( . motorway) ?? false
193235
194236 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+ } )
196249 } else if let ref = ref, isMotorway, let decimalRange = ref. rangeOfCharacter ( from: . decimalDigits) , !decimalRange. isEmpty {
197250 wayName = modifyValueByKey != nil ? " \( modifyValueByKey!( . code, ref) ) " : ref
198251 } else if name == nil , let ref = ref {
@@ -254,58 +307,27 @@ public class OSRMInstructionFormatter: Formatter {
254307 if step. finalHeading != nil { bearing = Int ( step. finalHeading! as Double ) }
255308
256309 // 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 " )
273325 }
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
296328 } else {
297- result += token! as String
329+ return modifyValueByKey ? ( tokenType , replacement ) ?? replacement
298330 }
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
309331 }
310332
311333 return result
0 commit comments