Rainbow Swift Library

repository·master·Indexed 24 days ago

https://github.com/onevcat/rainbow

A Swift library for adding text color, background color, and styles to console and command line output. It supports Apple platforms and Linux, featuring ANSI 256-color, True Color (24-bit), and HSL color models. The library provides String extensions for easy styling, a builder pattern via `.styled` for performance optimization, batch operations with `.applyingAll()`, and conditional styling APIs.

Tokens
4.4K
Snippets
18
Records
19
Agent score
84%

What's inside Rainbow

  1. Optimize performance with Batch Operations

    master

    Instead of chaining multiple styles which triggers multiple parsing cycles, use .applyingAll() to apply multiple styles in a single operation. This is more efficient for high-frequency styling.

    // Traditional - multiple parsing cycles
    let traditional = "Warning".red.bold.underline.italic
    
    // Optimized - single parsing cycle
    let optimized = "Warning".applyingAll(
        color: .named(.red), 
        styles: [.bold, .underline, .italic]
    )
  2. Optimize performance with the Builder Pattern

    master

    For complex styling involving multiple chained calls, use the .styled builder pattern. This is more efficient than traditional chaining because it uses lazy evaluation and generates a single string, avoiding the creation of multiple intermediate strings.

    Use .styled followed by your styles and end with .build().

    // Traditional chaining - creates multiple intermediate strings
    let traditional = "Hello".red.bold.underline.onBlue
    
    // Optimized builder pattern - lazy evaluation, single string generation  
    let optimized = "Hello".styled.red.bold.underline.onBlue.build()
  3. Optimize performance using the Builder Pattern

    master

    To avoid the performance degradation caused by multiple string copies in chained calls (e.g., "text".red.bold.underline), use the StyledStringBuilder or the .styled property. The builder pattern uses lazy evaluation, generating the final string only once when .build() is called, which can provide up to an 85% performance improvement for complex styling.

    // StyledStringBuilder with lazy evaluation
    public struct StyledStringBuilder {
        private let text: String
        private var color: ColorType?
        private var backgroundColor: BackgroundColorType?
        private var styles: [Style] = []
        
        // Lazy evaluation - only generates string when build() is called
        public func build() -> String {
            // Generate final string only once
        }
    }
  4. Install Rainbow via Swift Package Manager

    master

    To use Rainbow in your Swift project, add it as a dependency in your Package.swift file. This is recommended for cross-platform software development.

    import PackageDescription
    
    let package = Package(
        name: "YourAwesomeSoftware",
        dependencies: [
            .package(url: "https://github.com/onevcat/Rainbow", .upToNextMajor(from: "4.0.0"))
        ],
        targets: [
            .target(
                name: "MyApp",
                dependencies: ["Rainbow"]
            )
        ]
    )
    import PackageDescription
    
    let package = Package(
        name: "YourAwesomeSoftware",
        dependencies: [
            .package(url: "https://github.com/onevcat/Rainbow", .upToNextMajor(from: "4.0.0"))
        ],
        targets: [
            .target(
                name: "MyApp",
                dependencies: ["Rainbow"]
            )
        ]
    )
  5. Run Rainbow performance tests

    master

    You can benchmark your specific use cases by running the built-in performance test suite using swift test with a filter.

    # Run all performance tests
    swift test --filter PerformanceTests
    
    # Run specific performance tests
    swift test --filter PerformanceTests.testBuilderPatternPerformance
    swift test --filter PerformanceTests.testBatchOperationPerformance
  6. Use the Builder Pattern with `StyledStringBuilder` for complex styling

    master

    When applying multiple styles to a string, traditional chained calls (e.g., "text".red.bold) create multiple intermediate string copies, which is inefficient.

    To optimize performance and reduce memory pressure, use the .styled property to initiate the builder pattern and call .build() at the end. This uses lazy evaluation and generates the final string in a single pass, providing up to a ~578% performance improvement for complex chains.

    // ❌ Inefficient - creates multiple intermediate strings
    let slow = "Hello".red.bold.underline.onBlue
    
    // ✅ Efficient - lazy evaluation, single string generation
    let fast = "Hello".styled.red.bold.underline.onBlue.build()
  7. Maintain backward compatibility when using deprecated Rainbow APIs

    master

    Rainbow uses Swift's @available attribute to manage API transitions. If you are using older method names, you may see deprecation warnings. The library provides type aliases and renaming to ensure your code continues to work while guiding you toward the modern API.

    For example, bit8(_:) is being replaced by color256(_:), and bit24(_:_::) is being replaced by trueColor(_:_:_:).

    // Use type aliases and deprecation warnings
    public extension String {
        @available(*, deprecated, renamed: "color256")
        func bit8(_ color: UInt8) -> String { 
            return color256(color) 
        }
        
        @available(*, deprecated, renamed: "trueColor")
        func bit24(_ r: UInt8, _ g: UInt8, _ b: UInt8) -> String { 
            return trueColor(r, g, b) 
        }
    }
  8. Create custom style presets

    master

    While Rainbow does not provide opinionated default presets (like errorStyle), you can easily create your own by extending String. This allows you to maintain a consistent look and feel across your project while keeping the API consistent with Rainbow's property-based styling.

    // User-defined extension
    extension String {
        var error: String { self.red.bold }
        var success: String { self.green }
    }
  9. Optimize performance by avoiding repeated parsing

    master

    Avoid repeatedly applying styles to the same string inside loops. Instead, create a styled template once and reuse it with string formatting. This prevents the library from parsing and generating ANSI sequences for every iteration.

    // ❌ Don't repeatedly style the same string
    for i in 0..<1000 {
        print("Item \(i)".red.bold)  // Parses and generates 1000 times
    }
    
    // ✅ Style once, reuse the format
    let template = "Item %@".applyingAll(color: .named(.red), styles: [.bold])
    for i in 0..<1000 {
        print(String(format: template, "\(i)"))  // Only formats the number
    }
  10. Use Batch Operations with `applyingAll` for multiple styles

    master

    Instead of chaining multiple individual style properties, use the applyingAll method to apply a color, background color, and a set of styles in a single operation. This reduces the number of parsing and generation cycles, offering approximately a ~264% performance improvement.

    // ❌ Inefficient - multiple parsing and generation cycles
    let slow = "Hello".red.bold.underline.italic
    
    // ✅ Efficient - single parsing and generation cycle
    let fast = "Hello".applyingAll(
        color: .named(.red), 
        styles: [.bold, .underline, .italic]
    )
  11. Configure Color Output Target and Environment Variables

    master

    Rainbow automatically detects if the output is a TTY (e.g., a terminal) and will output plain text if writing to a file. You can override this behavior using the following priority:

    1. Explicit Code Setting: Set Rainbow.enabled in your code.
    2. Environment Variable FORCE_COLOR=1: Enables color even if the output is not a TTY (higher priority than NO_COLOR).
    3. Environment Variable NO_COLOR=1: Disables color.
    4. Manual Setting: Set Rainbow.outputTarget yourself.
  12. Basic Usage: Color and Style String Extensions

    master

    Rainbow provides convenient extensions on String to apply text color, background color, and styles (like bold or underline) using method chaining.

    Common patterns include:

    • .red, .blue, .cyan, etc., for text color.
    • .onBlue, .onWhite, etc., for background color.
    • .bold, .underline, .blink, etc., for text styles.
    • .clearColor, .clearBackgroundColor, and .clearStyles to reset attributes.
    import Rainbow
    
    print("Red text".red)
    print("Blue background".onBlue)
    print("Light green text on white background".lightGreen.onWhite)
    
    print("Underline".underline)
    print("Cyan with bold and blinking".cyan.bold.blink)
    
    print("Plain text".red.onYellow.bold.clearColor.clearBackgroundColor.clearStyles)