22
22
#import " SGUtils.h"
23
23
#import " GTLRUtilities.h"
24
24
25
+ @interface SGUtils ()
26
+ + (NSString *)stringOfLinesFromString : (NSString *)str
27
+ firstLinePrefix : (NSString *)firstLinePrefix
28
+ extraLinesPrefix : (NSString *)extraLinesPrefix
29
+ linesSuffix : (NSString *)linesSuffix
30
+ lastLineSuffix : (NSString *)lastLineSuffix
31
+ elementJoiner : (NSString *)elementJoiner
32
+ handleHTMLTags : (BOOL )handleHTMLTags ;
33
+ @end
34
+
25
35
static const NSUInteger kMaxWidth = 80 ;
26
36
27
37
@implementation SGHeaderDoc {
@@ -216,7 +226,8 @@ - (void)appendFirstIndent:(NSString *)firstIndent
216
226
extraLinesPrefix: extraLinePrefix
217
227
linesSuffix: @" "
218
228
lastLineSuffix: @" "
219
- elementJoiner: @" " ];
229
+ elementJoiner: @" "
230
+ handleHTMLTags: YES ];
220
231
[self internalAppend: wrapped];
221
232
}
222
233
@@ -392,6 +403,22 @@ + (NSString *)stringOfLinesFromString:(NSString *)str
392
403
linesSuffix : (NSString *)linesSuffix
393
404
lastLineSuffix : (NSString *)lastLineSuffix
394
405
elementJoiner : (NSString *)elementJoiner {
406
+ return [self stringOfLinesFromString: str
407
+ firstLinePrefix: firstLinePrefix
408
+ extraLinesPrefix: extraLinesPrefix
409
+ linesSuffix: linesSuffix
410
+ lastLineSuffix: lastLineSuffix
411
+ elementJoiner: elementJoiner
412
+ handleHTMLTags: NO ];
413
+ }
414
+
415
+ + (NSString *)stringOfLinesFromString : (NSString *)str
416
+ firstLinePrefix : (NSString *)firstLinePrefix
417
+ extraLinesPrefix : (NSString *)extraLinesPrefix
418
+ linesSuffix : (NSString *)linesSuffix
419
+ lastLineSuffix : (NSString *)lastLineSuffix
420
+ elementJoiner : (NSString *)elementJoiner
421
+ handleHTMLTags : (BOOL )handleHTMLTags {
395
422
if (str.length == 0 ) return nil ;
396
423
397
424
// Support forced new line by letting them through as words.
@@ -405,8 +432,50 @@ + (NSString *)stringOfLinesFromString:(NSString *)str
405
432
if (words.count > 1 ) {
406
433
str = [words componentsJoinedByString: @" \n " ];
407
434
}
435
+
408
436
NSCharacterSet *wsSet = [NSCharacterSet whitespaceCharacterSet ];
409
- words = [str componentsSeparatedByCharactersInSet: wsSet];
437
+ if (handleHTMLTags) {
438
+ // Clang's -Wdocumentation doesn't like word wrapping within an
439
+ // html tag. Xcode also seems to get confused by it when providing
440
+ // the contextual help. So this option looks for HTML tags and
441
+ // keeps them as a single thing to wordwrap.
442
+ static NSRegularExpression *regex;
443
+ static dispatch_once_t onceToken;
444
+ dispatch_once (&onceToken, ^{
445
+ // Match anything that isn't whitespace, '<', a letter, anything but '>',
446
+ // anything that isn't whitespace. This gets us anything before a tag and
447
+ // attached to the tag, and anything attached after it.
448
+ // NOTE: This is a little fragile, in that we don't want to catch things
449
+ // like "<= 12" or "<10".
450
+ regex = [NSRegularExpression regularExpressionWithPattern: @" \\ S*<[a-zA-Z][^<>]*>\\ S*"
451
+ options: 0
452
+ error: NULL ];
453
+ NSAssert (regex != nil , @" Ooops?" );
454
+ });
455
+ __block NSUInteger lastOffset = 0 ;
456
+ NSMutableArray *collector = [NSMutableArray array ];
457
+ [regex enumerateMatchesInString: str
458
+ options: 0
459
+ range: NSMakeRange (0 , str.length)
460
+ usingBlock: ^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
461
+ if (lastOffset != result.range .location ) {
462
+ // Everything before this match, split on whitespaces.
463
+ NSRange prevRange = NSMakeRange (lastOffset, result.range .location - lastOffset);
464
+ NSString *subStr = [str substringWithRange: prevRange];
465
+ [collector addObjectsFromArray: [subStr componentsSeparatedByCharactersInSet: wsSet]];
466
+ }
467
+ // Add this tag match so it will be wrapped as one chunk.
468
+ NSString *tag = [str substringWithRange: result.range];
469
+ [collector addObject: tag];
470
+ lastOffset = NSMaxRange (result.range );
471
+ }];
472
+ // Add anything left after the last match split on whitespece.
473
+ NSString *subStr = [str substringFromIndex: lastOffset];
474
+ [collector addObjectsFromArray: [subStr componentsSeparatedByCharactersInSet: wsSet]];
475
+ words = collector;
476
+ } else {
477
+ words = [str componentsSeparatedByCharactersInSet: wsSet];
478
+ }
410
479
411
480
// componentsSeparatedByCharactersInSet (and componentsSeparatedByString) is
412
481
// documented to take adjacent occurrences of the separator and produce empty
0 commit comments