Giter Club home page Giter Club logo

rainbow's Introduction

Rainbow

Rainbow adds text color, background color and style for console and command line output in Swift. It is born for cross-platform software logging in terminals, working in both Apple's platforms and Linux.

Basic Usage

Nifty way, using the String extension, and print the colorized string.

Named Color & Style

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)

It gives you something like this:

Installation

Swift Package Manager

If you are developing a cross platform software in Swift, Swift Package Manager might be your choice for package management. Just add the url of this repo to your Package.swift file as a dependency:

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"]
        )
    ]
)

Then run swift build whenever you get prepared.

You could know more information on how to use Swift Package Manager in Apple's official page.

Other Usage

String Interpolation & Nested

Swift string interpolation is supported. Define the color for part of the string. Or even create nested colorful strings. The inner color style will be kept:

print("接天莲叶\("无穷碧".green),映日荷花\("别样红".red)")
print("\("两只黄鹂".yellow)鸣翠柳,一行白鹭\("上青天".lightBlue)".lightGreen.underline)

ANSI 256-Color Mode

8-bit color is fully supported, for both text color and background color:

print("停车坐爱\("枫林晚".bit8(31))\("霜叶".bit8(160))红于\("二月花".bit8(198))")
print("\("一道残阳".bit8(202))铺水中,\("半江瑟瑟".bit8(30).onBit8(226))半江红。")

Hex Colors (approximated)

It also accepts a Hex color. Rainbow tries to convert it to a most approximate .bit8 color:

print("黑云压城\("城欲摧".hex("#666")),甲光向日\("金鳞开".hex("000000").onHex("#E6B422"))")
print("日出江花\("红胜火".hex(0xd11a2d)),春来江水\("绿如蓝".hex(0x10aec2))")

Valid format: "FFF", "#FFF", "FFFFFF", "#FFFFFF", 0xFFFFFF

True color

A few terminal emulators supports 24-bit true color. If you are sure the 24-bit colors can be displayed in your user's terminal, Rainbow has no reason to refuse them!

print("疏影横斜\("水清浅".bit24(36,116,181)),暗香浮动\("月黄昏".bit24(254,215,26))")
print("\("春色满园".hex("#ea517f", to: .bit24))关不住,\("一枝红杏".hex("#f43e06", to: .bit24))出墙来。")

Output Target

By default, Rainbow should be smart enough to detect the output target, to determine if it is a tty. For example, it automatically output plain text if written to a file:

// main.swift
print("Hello Rainbow".red)

$ .build/debug/RainbowDemo > output.txt

// output.txt
Hello Rainbow

This is useful for sharing the same code for logging to console and to a log file.

You can manually change this behavior by either:

  • Set the Rainbow.outputTarget yourself.
  • Pass a "NO_COLOR" environment value when executing your app.
  • Or set the Rainbow.enabled to false.

Verbose Way

You can also use the more verbose way if you want:

import Rainbow
let output = "The quick brown fox jumps over the lazy dog"
                .applyingCodes(Color.red, BackgroundColor.yellow, Style.bold)
print(output) // Red text on yellow, bold of course :)

Or even construct everything from scratch:

let entry = Rainbow.Entry(
    segments: [
        .init(text: "Hello ", color: .named(.magenta)),
        .init(text: "Rainbow", color: .bit8(214), backgroundColor: .named(.lightBlue), styles: [.underline]),
    ]
)
print(Rainbow.generateString(for: entry))

Please remember, the string extensions (such as "Hello".red) is O(n). So if you are handling a huge string or very complex nesting, there might be a performance issue or hard to make things in stream. The manual way is a rescue for these cases.

Motivation and Compatibility

Thanks to the open source of Swift, developers now could write cross platform programs with the same language. And I believe the command line software would be the next great platform for Swift. Colorful and well-organized output always helps us to understand what happens. It is really a necessary utility to create wonderful software.

Rainbow should work well in both OS X and Linux terminals. It is smart enough to check whether the output is connected to a valid text terminal or not, to decide the log should be modified or not. This could be useful when you want to send your log to a file instead to console.

Contact

Follow and contact me on Twitter or Sina Weibo. If you find an issue, just open a ticket on it. Pull requests are warmly welcome as well.

Backers & Sponsors

Open-source projects cannot live long without your help. If you find Kingfisher is useful, please consider supporting this project by becoming a sponsor. Your user icon or company logo shows up on my blog with a link to your home page.

Become a sponsor through GitHub Sponsors. ❤️

License

Rainbow is released under the MIT license. See LICENSE for details.

rainbow's People

Contributors

apollozhu avatar codafi avatar dependabot[bot] avatar dlmarquis avatar dreymonde avatar eneko avatar fredloh avatar msanders avatar onevcat avatar pvieito avatar rbukovansky avatar regexident avatar tzxdtc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rainbow's Issues

No such module 'Rainbow'

I followed the directions in the readme file and while I'm able to see Rainbow install when I add the .package(url: "https://github.com/onevcat/Rainbow", from: "3.0.0") line to the dependencies array, I get No such module Rainbow when I attempt to import it in main.swift.

I tried adding it to targets, too, like so:

    targets: [
        .target(
            name: "MyCLIUtility",
            dependencies: ["SPMUtility", "Rainbow"]),
        .testTarget(
            name: "MyCLIUtilityTests",
            dependencies: ["MyCLIUtility"]),
    ]

What am I missing?

Does it really work on linux?

Here is a minimal example:

import Foundation
import Rainbow // marathon: https://github.com/onevcat/Rainbow.git

print("teste".lightGreen)

Which, under Ubuntu 18.04 does not generate any color. Am I doing something wrong?

Manual Installation

CocoaPods and Carthage are awesome tools and make our life really easier, but there are some devs who still don't know how to use them.

It would be cool to add the Manual installation guide in your README.md. You can take a look at my iOS Readme Template to see how you can do it.

Optional Errors

These two lines return an optional value now, and are throwing the error Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?

I'm not sure what the best way to handle this would be for this project, but in the return line, maybe doing something like return (codes, text ?? "")

let text = String(string[startIndex ..< endIndex])

let text = String(string[startIndex ..< endIndex])

Assistance in writing a Regex to remove Rainbow information

First of all, thank you for putting together this library. It's great work!

I share your motivation that Swift will become incredibly useful for command line programs. This is the reason that I started SwiftyTextTable to better organize complex console output.

I think our libraries are a natural pair, and I would like to make them work seamlessly together. Unfortunately, right now the escape sequences that Rainbow uses to inject color and style information are not compatible with my (rather naive) method of calculating string lengths to determine column widths. This is being tracked in this issue: scottrhoyt/SwiftyTextTable#5.

It would be my preference to not introduce a dependency on Rainbow to keep the library as lightweight as possible. Therefore I was wondering if you could assist me in designing an algorithm to strip Rainbow styles and colors from a string for length calculations. From my light reading of the extraction methods already present in Rainbow, it looks like I can detect the presence of a formatted string, and if necessary, apply a regex to extract the text information out of the style information, but I would like to hear your thoughts on implementation. Thanks!

usage for iOS project

could this use for iOS project? i use this in my iOS project , and it doesn't work(doesn't show extra console).
what i' done was:
1.add RainbowSwift in my pod file (with right swift version)
2.import RainbowSwift
3.print("xxxxx".red)

please help

Style doesn't get reset for substring

Hello,

This simple code has an unexpected result:

print(("a" + "b".underline + "c").lightGreen)

I would expect the whole string to be in green, and the b only to be underlined, however the underlining doesn't get reset, so the c gets underlined too!

Expected result: \e[92ma\e[92;4mb\e[0;92mc\e[0m
Actual result: \e[92ma\e[92;4mb\e[92mc\e[0m
abc with both b and c underlined

This happens with all styles when applied to a substring where a foreground color is inherited.

Crossline support

There is no reason that we do not add the crossline support to Style.

Segment group doesn't work for `backgroundColor` and `styles`.

Wei, thanks for your contribution to this project, my new tool relies on it strongly.

After upgrading to the new version 4.0.0, I use the following code to join a colorful message in terminal console, but got something unexpected results:

import RainbowSwift

let entry = Rainbow.Entry(
    segments: [
        .init(text: "Hello ", color: .named(.magenta)),
        .init(text: "Rainbow ", color: .bit8(214), backgroundColor: .named(.black), styles: [.underline]),
        .init(text: "Hello ", color: .named(.magenta)/*, backgroundColor: .named(.default)*/),  // Comment 1
        .init(text: "again", color: .named(.magenta), backgroundColor: .named(.red)/*, styles: [.default]*/),  // Comment 2
    ]
)
print(Rainbow.generateString(for: entry))

It shows the black background and styles from the second segment on the second Hello, this is weird, the underline style also affects to the last segment:
1

If I uncomment the Comment 1 only:
2

If I uncoment the Comment 2 only:
3

Uncomment both:
4

I really don't know how to explain them even after trying to look into the Rainbow inside, please confirm is it a bug or how should I use the Segment.
Thanks!

readme outdated

just tried to install via cocoapods and ran into a buttload of errors:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

pod 'RainbowSwift', '~> 1.1'

installed again without '~> 1.1' and it went fine

Swift 3 compatibility

Hey, I'd love to see this lib available in Swift 3 so I can implement it in my project.

Thanks 😄

Still black

My logs are still black. When I set Environment Variable "XcodeColors" to YES, my output is like this: �[fg255,0,0;Recognized a double tap�[;

Cocopod 1.1 doesn't output colors

Using Xcode 7.3 cocopods. I added Rainbow in the Podfile per your README. I also remembered to import RaindobowSwift (vs Rainbow). Now, when I try to use it, type-ahead shows me the colors so I know the class is being read. However, no text comes out colored. (ie print("hello myself".red) just prints "hello myself" in the normal console color. I feel like xcode is somehow overriding the coloring maybe.

Ideas?

PS I am in a bridged obj-c/swift project if that's a clue. However, I am only trying this from the Swift side without luck...

Empty output in a file

In my command line tool, when I add > filename.txt to output results in a file, it creates an empty file. The output is provided in the console though.

See more details: rsrbk/GoSwifty#3

Add conversion from BackgroundColor to its Color counterpart

Hey there. I'm trying to build a string similar to a Powerline prompt.

It's a series of segments, separated by a custom powerline triangle glyph. The glyph is coloured predicably: the triangle part of is coloured based on the text colour, and the background is coloured based on the background. But the glyph exists to
connect two different background colours.

This means you want to set its text colour to the equivalent of the background colour of whats to the left, and the background colour to be equal to the background colour of whats to the right. To achieve this, you need a way of converting a BackgroundColor to its Color counterpart.

Here's my example:

import Rainbow

extension BackgroundColor {
	var toTextColor: Color {
		switch self {
		case .black:	return .black
		case .red:		return .red
		case .green:	return .green
		case .yellow:	return .yellow
		case .blue:		return .blue
		case .magenta:	return .magenta
		case .cyan:		return .cyan
		case .white:	return .white
		case .default:	return .default
		}
	}
}

struct Segment {
	let text: String
	let textColor: Color = .default
	let backgroundColor: BackgroundColor
}

extension Collection where Element == Segment {
	func joined() -> String {
		let dummySegment = Segment(text: "", backgroundColor: .default)
		
		let strings = zip(self, self.dropFirst() + [dummySegment]).map { current, next -> String in
			let separator = "".applyingCodes(current.backgroundColor.toTextColor, next.backgroundColor)
			let text = current.text.applyingCodes(current.textColor, current.backgroundColor)
			return text + separator
		}
		
		return strings.joined()
	}
}

let segments = [
	Segment(text: "abc", backgroundColor: .red),
	Segment(text: "def", backgroundColor: .green),
	Segment(text: "ghi", backgroundColor: .blue),
]

let result = segments.joined() + " The rest of the message"

print("before\n")
print(result)
print("\nafter")

Output (rendered in SF mono nerd font:

image

I wanted to contribute the implementation of toTextColor, because I think it might be useful to others. The reverse direction might also be useful, though there are more Colors than can map onto BackgroundColors, so its unclear how to handle the unmappable cases (make the computed property optional and return nil?)

Do you think this would be useful for me to contribute?

If so, how do you think I should write the test for it?

Clear string colors

Hi, I ❤️ using Rainbow in my projects.

I am however stumbling across an issue where I need to use the length of a string as in .characters.count or just .count in Swift 4. Obviously this changes when introducing escape sequences, so I was looking for a way to remove these. Rainbow offers the handy .removingColor() method on strings, but unfortunately this seems to just replace the escape sequences with default values. Is there a way to access only the actual string content itself? That would be fantastic!

.stringByApplying doesn't work

Following to the documentation, I tried the code

let output = "The quick brown fox jumps over the lazy dog"
            .stringByApplying(Color.Red, BackgroundColor.Yellow, Style.Bold)

but the code didn't compile with the error

error: value of type 'String' has no member 'stringByApplying'
        let output = "The quick brown fox jumps over the lazy dog"
                     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.