@@ -15,9 +15,9 @@ import Foundation
1515 - [The 8-bits colors table (direct image link)](<https://i.stack.imgur.com/KTSQa.png>);
1616 - [List of Terminals supporting True Colors](<https://gist.github.com/XVilka/8346728>);
1717 - [The ODA Specs](<https://en.wikipedia.org/wiki/Open_Document_Architecture#External_links>) aka. CCITT T.411-T.424 (equivalent to ISO 8613, but freely downloadable). */
18- public struct SGR : Hashable , CustomStringConvertible , CLTLogger_Sendable {
18+ public struct SGR : RawRepresentable , Hashable , CustomStringConvertible , CLTLogger_Sendable {
1919
20- public enum Modifier : Hashable , CustomStringConvertible , CLTLogger_Sendable {
20+ public enum Modifier : RawRepresentable , Hashable , CustomStringConvertible , CLTLogger_Sendable {
2121
2222 /** Reset/Normal -- All attributes off. */
2323 case reset
@@ -441,8 +441,7 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
441441 }
442442 }
443443
444- @available ( macOS 10 . 15 , iOS 13 . 0 , * )
445- init ? ( rawValue: String ) {
444+ public init ? ( rawValue: String ) {
446445 let s = Scanner ( forParsing: rawValue)
447446
448447 self . init ( scanner: s)
@@ -452,23 +451,22 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
452451 }
453452 }
454453
455- /* Note: This init probably has terrible perfs, which is why it is internal (only used in the tests). */
456- @available ( macOS 10 . 15 , iOS 13 . 0 , * )
454+ /* Note: This init probably has terrible perfs. */
457455 init ? ( scanner: Scanner ) {
458456 struct DummyError : Error { }
459- let originalScannerIndex = scanner. currentIndex
457+ let originalScanLocation = scanner. compatibleScanLocation
460458 do {
461459 enum ColorDestination : String {
462460 case fg = " 38 "
463461 case bg = " 48 "
464462 case ul = " 58 "
465463 }
466- let token = scanner. scanUpToCharacters ( from: CharacterSet ( charactersIn: String ( Self . separatorChar) + String( SGR . sgrEndChar) ) ) ?? " "
464+ let token = scanner. xl_scanUpToCharacters ( from: CharacterSet ( charactersIn: String ( Self . separatorChar) + String( SGR . sgrEndChar) ) ) ?? " "
467465 if token. contains ( " : " ) {
468466 /* Let’s process the special ODA cases. */
469467 let subScanner = Scanner ( forParsing: token)
470- let subToken = subScanner. scanUpToString ( " : " ) ?? " "
471- _ = subScanner. scanString ( " : " ) ! /* !: The string contains a colon, so the scan cannot fail. */
468+ let subToken = subScanner. xl_scanUpToString ( " : " ) ?? " "
469+ _ = subScanner. xl_scanString ( " : " ) ! /* !: The string contains a colon, so the scan cannot fail. */
472470
473471 let isFgColor : Bool
474472 switch subToken {
@@ -479,7 +477,7 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
479477 * Note however, it might be possible to get the 58 case too (underline color), though because it is not part of the ODA it shouldn’t be valid with this notation. */
480478 throw DummyError ( )
481479 }
482- let colorFormat = subScanner. scanUpToString ( " : " ) ?? " "
480+ let colorFormat = subScanner. xl_scanUpToString ( " : " ) ?? " "
483481 switch colorFormat {
484482 case " 0 " , " " :
485483 guard isFgColor, subScanner. isAtEnd else {
@@ -501,10 +499,10 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
501499 func scanParam( ) throws -> Int ? {
502500 if subScanner. isAtEnd { return nil }
503501 else {
504- guard subScanner. scanString ( " : " ) != nil else {
502+ guard subScanner. xl_scanString ( " : " ) != nil else {
505503 throw DummyError ( )
506504 }
507- guard let str = subScanner. scanUpToString ( " : " ) else {
505+ guard let str = subScanner. xl_scanUpToString ( " : " ) else {
508506 return nil
509507 }
510508 /* We assume “+1” is a valid value. */
@@ -581,9 +579,9 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
581579 }
582580 if let colorDestination = ColorDestination ( rawValue: token) {
583581 guard
584- scanner. scanCharacter ( ) == Self . separatorChar,
585- let colorType = scanner. scanCharacter ( ) ,
586- scanner. scanCharacter ( ) == Self . separatorChar
582+ scanner. xl_scanCharacter ( ) == Self . separatorChar,
583+ let colorType = scanner. xl_scanCharacter ( ) ,
584+ scanner. xl_scanCharacter ( ) == Self . separatorChar
587585 else {
588586 throw DummyError ( )
589587 }
@@ -602,19 +600,19 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
602600 /* Wikipedia says empty values are treated as 0.
603601 * But Terminal for instance does not seem to know that.
604602 * We don’t care, we do like Wikipedia says. */
605- let r = try uint8 ( scanner. scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
606- guard scanner. scanCharacter ( ) == Self . separatorChar else { throw DummyError ( ) }
607- let g = try uint8 ( scanner. scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
608- guard scanner. scanCharacter ( ) == Self . separatorChar else { throw DummyError ( ) }
609- let b = try uint8 ( scanner. scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
603+ let r = try uint8 ( scanner. xl_scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
604+ guard scanner. xl_scanCharacter ( ) == Self . separatorChar else { throw DummyError ( ) }
605+ let g = try uint8 ( scanner. xl_scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
606+ guard scanner. xl_scanCharacter ( ) == Self . separatorChar else { throw DummyError ( ) }
607+ let b = try uint8 ( scanner. xl_scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
610608 switch colorDestination {
611609 case . fg: self = . fgColorToRGB( red: r, green: g, blue: b) ; return
612610 case . bg: self = . bgColorToRGB( red: r, green: g, blue: b) ; return
613611 case . ul: self = . underlineColorToRGB( red: r, green: g, blue: b) ; return
614612 }
615613
616614 case " 5 " :
617- let v = try uint8 ( scanner. scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
615+ let v = try uint8 ( scanner. xl_scanUpToString ( String ( Self . separatorChar) ) ?? " 0 " )
618616 switch colorDestination {
619617 case . fg: self = . fgColorTo256PaletteValue( v) ; return
620618 case . bg: self = . bgColorTo256PaletteValue( v) ; return
@@ -709,7 +707,7 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
709707 default : throw DummyError ( )
710708 }
711709 } catch {
712- scanner. currentIndex = originalScannerIndex
710+ scanner. compatibleScanLocation = originalScanLocation
713711 return nil
714712 }
715713 }
@@ -745,8 +743,7 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
745743 self . modifiers = modifiers
746744 }
747745
748- @available ( macOS 10 . 15 , iOS 13 . 0 , * )
749- init ? ( rawValue: String ) {
746+ public init ? ( rawValue: String ) {
750747 let s = Scanner ( forParsing: rawValue)
751748
752749 self . init ( scanner: s)
@@ -757,21 +754,20 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
757754 }
758755
759756 /* For symetry w/ SGR.Modifier init, but not really needed, at least for now. */
760- @available ( macOS 10 . 15 , iOS 13 . 0 , * )
761757 init ? ( scanner: Scanner ) {
762758 struct DummyError : Error { }
763- let originalScannerIndex = scanner. currentIndex
759+ let originalScanLocation = scanner. compatibleScanLocation
764760 do {
765761 guard
766- scanner. scanCharacter ( ) == Self . escapeChar,
767- scanner. scanCharacter ( ) == Self . csiChar
762+ scanner. xl_scanCharacter ( ) == Self . escapeChar,
763+ scanner. xl_scanCharacter ( ) == Self . csiChar
768764 else {
769765 /* Not a CSI. */
770766 throw DummyError ( )
771767 }
772768
773- let csiContent = scanner. scanUpToCharacters ( from: Self . possibleFinalByte) ?? " "
774- guard scanner. scanCharacter ( ) == Self . sgrEndChar else {
769+ let csiContent = scanner. xl_scanUpToCharacters ( from: Self . possibleFinalByte) ?? " "
770+ guard scanner. xl_scanCharacter ( ) == Self . sgrEndChar else {
775771 /* Not an SGR. */
776772 throw DummyError ( )
777773 }
@@ -785,15 +781,15 @@ public struct SGR : Hashable, CustomStringConvertible, CLTLogger_Sendable {
785781 /* A modifier has been parsed.
786782 * Either scan location is now at a semicolon or at the end.
787783 * If on semicolon we must consume it. */
788- let c = contentScanner. scanCharacter ( )
784+ let c = contentScanner. xl_scanCharacter ( )
789785 assert ( c == Modifier . separatorChar)
790786 }
791787 guard contentScanner. isAtEnd else {
792788 /* Not all modifiers parsed in the content. */
793789 throw DummyError ( )
794790 }
795791 } catch {
796- scanner. currentIndex = originalScannerIndex
792+ scanner. compatibleScanLocation = originalScanLocation
797793 return nil
798794 }
799795 }
0 commit comments