New Upstream Release - golang-github-logrusorgru-aurora
Ready changes
Summary
Merged new upstream version: 4.0.0 (was: 3.0.0).
Resulting package
Built on 2022-12-14T18:22 (took 7m25s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases golang-github-logrusorgru-aurora-dev
Lintian Result
Diff
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..854d257
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,61 @@
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+
+name: build
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v3
+ with:
+ go-version: 1.19
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run linters
+ uses: golangci/golangci-lint-action@v3
+ with:
+ version: v1.46.2
+
+ test:
+ strategy:
+ matrix:
+ go-version: [1.19]
+ platform: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{ matrix.platform }}
+ steps:
+ - name: Install Go
+ if: success()
+ uses: actions/setup-go@v3
+ with:
+ go-version: ${{ matrix.go-version }}
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Run tests
+ run: go test -v -covermode=count
+
+ coverage:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install Go
+ if: success()
+ uses: actions/setup-go@v3
+ with:
+ go-version: 1.19
+ - name: Checkout code
+ uses: actions/checkout@v2
+ - name: Calc coverage
+ run: |
+ go test -v -covermode=count -coverprofile=coverage.out
+ - name: Convert coverage.out to coverage.lcov
+ uses: jandelgado/gcov2lcov-action@v1
+ - name: Coveralls
+ uses: coverallsapp/github-action@v1.1.2
+ with:
+ github-token: ${{ secrets.github_token }}
+ path-to-lcov: coverage.lcov
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 570e361..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-language: go
-go:
- - tip
-before_install:
- - go get github.com/axw/gocov/gocov
- - go get github.com/mattn/goveralls
- - go get golang.org/x/tools/cmd/cover
-script:
- - $HOME/gopath/bin/goveralls -service=travis-ci
diff --git a/AUTHORS.md b/AUTHORS.md
index 0ee9e3e..d268f53 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -6,3 +6,4 @@ AUTHORS
- Ousmane Traore @otraore
- Simon Legner @simon04
- Sevenate @sevenate
+- JP Hastings-Spital @jphastings
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad0a202..ba5886b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,45 @@
Changes
=======
+---
+14:15:14
+Thursday, October 8, 2022
+
+New version v4. Breaking changes. [Migrate from v3](#migrate-from-v3).
+
+- Drop deprecated `Bleach` methods. Use `Reset` or `Clear` instead.
+- Drop deprecated `Brows` and `BgBrows` methods, and `BrownFg` and `BrownBg`
+ colors. Use `Yellow` variants instead.
+- Instead of `Aurora` interface introduced `Aurora` structure.
+- Instead of `Value` interface introduced `Value` structure.
+- Implemented [hyperlinks feature](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda).
+ - added `Hyperlink` method
+ - added `HyperlinkTarget` and `HyperlinkParams` methods
+ - added `HyperlinkParam` type, `IsValidHyperlinkTarget`,
+ `IsValidHyperlinkParam`, `HyperlinkID`, `HyperlinkEscape`,
+ `HyperlinkUnescape` helper functions.
+- Introduced `Config` and related functions and methods, such as `NewConfig`,
+ `WithColors`, `WithHyperlinks`.
+- Removed `NewAurora` function, new function `New` introduced.
+- Introduced global `DefaultColorizer` that used by package root methods.
+- `Sprintf` method now belongs to a colorizer and depends on its configurations.
+ For package root `Sprintf` it's the `DefaultColorizer`.
+
+Performance for all methods is almost the same. But for color- and
+format-methods `aurora` now takes less allocations. But, unfortunately, for
+`Sprintf` it takes more allocations.
+
+###### Migrate from v3
+
+1. Use `Reset` or `Clear` instead of `Bleach`.
+2. Use `Yellow` instead of `Brows`.
+3. Use `BgYellow` instead of `BgBrown`.
+4. Use `YellowFg` instead of `BrownFg`.
+5. Use `YellowBg` instead of `BrownBg`.
+6. Use `New` instead of `NewAurora`.
+7. Use `New(WithColors(false))` to disable colors.
+8. Use `New(WithHyperlinks(false))` to disable hyperlinks.
+
---
16:05:02
Thursday, July 2, 2020
diff --git a/README.md b/README.md
index fbc26bf..314a88b 100644
--- a/README.md
+++ b/README.md
@@ -3,10 +3,9 @@ Aurora
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/logrusorgru/aurora/v3?tab=doc)
[![Unlicense](https://img.shields.io/badge/license-unlicense-blue.svg)](http://unlicense.org/)
-[![Build Status](https://travis-ci.org/logrusorgru/aurora.svg)](https://travis-ci.org/logrusorgru/aurora)
-[![Coverage Status](https://coveralls.io/repos/logrusorgru/aurora/badge.svg?branch=master)](https://coveralls.io/r/logrusorgru/aurora?branch=master)
+[![Build Status](https://github.com/logrusorgru/aurora/workflows/build/badge.svg)](https://github.com/logrusorgru/aurora/actions?workflow=build)
+[![Coverage Status](https://coveralls.io/repos/github/logrusorgru/aurora/badge.svg?branch=master)](https://coveralls.io/github/logrusorgru/aurora?branch=master)
[![GoReportCard](https://goreportcard.com/badge/logrusorgru/aurora)](https://goreportcard.com/report/logrusorgru/aurora)
-[![Gitter](https://img.shields.io/badge/chat-on_gitter-46bc99.svg?logo=data:image%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTQiIHdpZHRoPSIxNCI%2BPGcgZmlsbD0iI2ZmZiI%2BPHJlY3QgeD0iMCIgeT0iMyIgd2lkdGg9IjEiIGhlaWdodD0iNSIvPjxyZWN0IHg9IjIiIHk9IjQiIHdpZHRoPSIxIiBoZWlnaHQ9IjciLz48cmVjdCB4PSI0IiB5PSI0IiB3aWR0aD0iMSIgaGVpZ2h0PSI3Ii8%2BPHJlY3QgeD0iNiIgeT0iNCIgd2lkdGg9IjEiIGhlaWdodD0iNCIvPjwvZz48L3N2Zz4%3D&logoWidth=10)](https://gitter.im/logrusorgru/aurora)
Ultimate ANSI colors for Golang. The package supports Printf/Sprintf etc.
@@ -21,6 +20,7 @@ Ultimate ANSI colors for Golang. The package supports Printf/Sprintf etc.
+ [Printf](#printf)
+ [aurora.Sprintf](#aurorasprintf)
+ [Enable/Disable colors](#enabledisable-colors)
+ + [Hyperlinks, default colorizer, and configurations](#hyperlinks-default-colorizer-and-configurations)
- [Chains](#chains)
- [Colorize](#colorize)
- [Grayscale](#grayscale)
@@ -37,7 +37,7 @@ Ultimate ANSI colors for Golang. The package supports Printf/Sprintf etc.
# Installation
-### Version 1.x
+##### Version 1.x
Using gopkg.in.
@@ -45,13 +45,13 @@ Using gopkg.in.
go get -u gopkg.in/logrusorgru/aurora.v1
```
-### Version 2.x
+##### Version 2.x
```
go get -u github.com/logrusorgru/aurora
```
-### Go modules support, version v3+
+##### Go modules support, version v3+
Get
```
@@ -61,10 +61,18 @@ go get -u github.com/logrusorgru/aurora/v3
The v3 was introduced to support `go.mod` and leave previous import paths as is.
Currently, there is no changes between them (excluding the importpath's /v3 tail).
+##### The latest version
+
+```
+go get -u github.com/logrusorgru/aurora/v4
+```
+
+With hyperlinks.
+
# Test
```
-go test -cover github.com/logrusorgru/aurora/v3
+go test -cover -race github.com/logrusorgru/aurora/v4
```
Replace the import path with your, if it's different.
@@ -79,12 +87,12 @@ package main
import (
"fmt"
- . "github.com/logrusorgru/aurora"
+ "github.com/logrusorgru/aurora/v4"
)
func main() {
- fmt.Println("Hello,", Magenta("Aurora"))
- fmt.Println(Bold(Cyan("Cya!")))
+ fmt.Println("Hello,", aurora.Magenta("Aurora"))
+ fmt.Println(aurora.Bold(aurora.Cyan("Cya!")))
}
```
@@ -99,12 +107,12 @@ package main
import (
"fmt"
- . "github.com/logrusorgru/aurora"
+ "github.com/logrusorgru/aurora/v4"
)
func main() {
- fmt.Printf("Got it %d times\n", Green(1240))
- fmt.Printf("PI is %+1.2e\n", Cyan(3.14))
+ fmt.Printf("Got it %d times\n", aurora.Green(1240))
+ fmt.Printf("PI is %+1.2e\n", aurora.Cyan(3.14))
}
```
@@ -119,11 +127,11 @@ package main
import (
"fmt"
- . "github.com/logrusorgru/aurora"
+ "github.com/logrusorgru/aurora/v4"
)
func main() {
- fmt.Println(Sprintf(Magenta("Got it %d times"), Green(1240)))
+ fmt.Println(aurora.Sprintf(aurora.Magenta("Got it %d times"), aurora.Green(1240)))
}
```
@@ -139,17 +147,17 @@ import (
"fmt"
"flag"
- "github.com/logrusorgru/aurora"
+ "github.com/logrusorgru/aurora/v4"
)
// colorizer
-var au aurora.Aurora
+var au *aurora.Aurora
var colors = flag.Bool("colors", false, "enable or disable colors")
func init() {
flag.Parse()
- au = aurora.NewAurora(*colors)
+ au = aurora.New(WithColors(*colors))
}
func main() {
@@ -158,22 +166,53 @@ func main() {
}
```
-Without flags:
+Without flags:
![disable png](https://github.com/logrusorgru/aurora/blob/master/disable.png)
-
+
With `-colors` flag:
![enable png](https://github.com/logrusorgru/aurora/blob/master/enable.png)
+### Hyperlinks, default colorizer, and configurations
+
+[Hyperlinks feature description](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda).
+
+Add a red hyperlinks with text "Example" that is referencing to
+http://example.com.
+
+```go
+package main
+
+import (
+ "flag"
+ "fmt"
+
+ "github.com/logrusorgru/aurora/v4"
+)
+
+func main() {
+ var conf = aurora.NewConfig()
+ conf.AddFlags(flag.CommandLine, "prefix.")
+ flag.Parse()
+
+ aurora.DefaultColorizer = aurora.New(conf.Options()...) // set global
+
+ fmt.Println(aurora.Red("Example").Hyperlink("http://example.com/"))
+}
+```
+Depending flags:
+![depending flags png](https://github.com/logrusorgru/aurora/blob/master/aurora_hyperlinks_flags.png)
+![depending flags gif](https://github.com/logrusorgru/aurora/blob/master/aurora_hyperlinks.gif)
+
# Chains
The following samples are equal
```go
-x := BgMagenta(Bold(Red("x")))
+x := aurora.BgMagenta(aurora.Bold(aurora.Red("x")))
```
```go
-x := Red("x").Bold().BgMagenta()
+x := aurora.Red("x").Bold().BgMagenta()
```
The second is more readable
@@ -192,34 +231,34 @@ func getColors() Color {
// [...]
func main() {
- fmt.Println(Colorize("Greeting", getColors()))
+ fmt.Println(aurora.Colorize("Greeting", getColors()))
}
```
Less complicated example
```go
-x := Colorize("Greeting", GreenFg|GrayBg|BoldFm)
+x := aurora.Colorize("Greeting", GreenFg|GrayBg|BoldFm)
```
Unlike other color functions and methods (such as Red/BgBlue etc)
a `Colorize` clears previous colors
```go
-x := Red("x").Colorize(BgGreen) // will be with green background only
+x := aurora.Red("x").Colorize(BgGreen) // will be with green background only
```
# Grayscale
```go
fmt.Println(" ",
- Gray(1-1, " 00-23 ").BgGray(24-1),
- Gray(4-1, " 03-19 ").BgGray(20-1),
- Gray(8-1, " 07-15 ").BgGray(16-1),
- Gray(12-1, " 11-11 ").BgGray(12-1),
- Gray(16-1, " 15-07 ").BgGray(8-1),
- Gray(20-1, " 19-03 ").BgGray(4-1),
- Gray(24-1, " 23-00 ").BgGray(1-1),
+ aurora.Gray(1-1, " 00-23 ").BgGray(24-1),
+ aurora.Gray(4-1, " 03-19 ").BgGray(20-1),
+ aurora.Gray(8-1, " 07-15 ").BgGray(16-1),
+ aurora.Gray(12-1, " 11-11 ").BgGray(12-1),
+ aurora.Gray(16-1, " 15-07 ").BgGray(8-1),
+ aurora.Gray(20-1, " 19-03 ").BgGray(4-1),
+ aurora.Gray(24-1, " 23-00 ").BgGray(1-1),
)
```
@@ -236,6 +275,22 @@ Methods `Index` and `BgIndex` implements 8-bit colors.
| 16-231 | 216 colors | 38;5;n | 48;5;n |
| 232-255 | 24 grayscale | 38;5;n | 48;5;n |
+Example
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/logrusorgru/aurora"
+)
+
+func main() {
+ for i := uint8(16); i <= 231; i++ {
+ fmt.Println(i, aurora.Index(i, "pew-pew"), aurora.BgIndex(i, "pew-pew"))
+ }
+}
+```
# Supported colors & formats
@@ -295,13 +350,15 @@ package main
import (
"fmt"
- . "github.com/logrusorgru/aurora"
+ "github.com/logrusorgru/aurora"
)
func main() {
- r := Red("red")
- var i int
- fmt.Printf("%T %p\n", r, Green(&i))
+ var (
+ r = aurora.Red("red")
+ i int
+ )
+ fmt.Printf("%T %p\n", r, aurora.Green(&i))
}
```
@@ -315,7 +372,7 @@ The obvious workaround is `Red(fmt.Sprintf("%T", some))`
### Windows
-The Aurora provides ANSI colors only, so there is no support for Windows. That said, there are workarounds available.
+The Aurora provides ANSI colors only, so there is no support for Windows. That said, there are workarounds available.
Check out these comments to learn more:
- [Using go-colorable](https://github.com/logrusorgru/aurora/issues/2#issuecomment-299014211).
@@ -329,9 +386,7 @@ on colors for a terminal only, and turn them off for a file.
### Licensing
-Copyright © 2016-2020 The Aurora Authors. This work is free.
+Copyright © 2016-2022 The Aurora Authors. This work is free.
It comes without any warranty, to the extent permitted by applicable
law. You can redistribute it and/or modify it under the terms of the
the Unlicense. See the LICENSE file for more details.
-
-
diff --git a/aurora.go b/aurora.go
index 3b30230..66b644b 100644
--- a/aurora.go
+++ b/aurora.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -36,690 +36,767 @@
// Package aurora implements ANSI-colors
package aurora
-import (
- "fmt"
-)
-
-// An Aurora implements colorizer interface.
-// It also can be a non-colorizer
-type Aurora interface {
-
- // Reset wraps given argument returning Value
- // without formats and colors.
- Reset(arg interface{}) Value
-
- //
- // Formats
- //
- //
- // Bold or increased intensity (1).
- Bold(arg interface{}) Value
- // Faint, decreased intensity (2).
- Faint(arg interface{}) Value
- //
- // DoublyUnderline or Bold off, double-underline
- // per ECMA-48 (21).
- DoublyUnderline(arg interface{}) Value
- // Fraktur, rarely supported (20).
- Fraktur(arg interface{}) Value
- //
- // Italic, not widely supported, sometimes
- // treated as inverse (3).
- Italic(arg interface{}) Value
- // Underline (4).
- Underline(arg interface{}) Value
- //
- // SlowBlink, blinking less than 150
- // per minute (5).
- SlowBlink(arg interface{}) Value
- // RapidBlink, blinking 150+ per minute,
- // not widely supported (6).
- RapidBlink(arg interface{}) Value
- // Blink is alias for the SlowBlink.
- Blink(arg interface{}) Value
- //
- // Reverse video, swap foreground and
- // background colors (7).
- Reverse(arg interface{}) Value
- // Inverse is alias for the Reverse
- Inverse(arg interface{}) Value
- //
- // Conceal, hidden, not widely supported (8).
- Conceal(arg interface{}) Value
- // Hidden is alias for the Conceal
- Hidden(arg interface{}) Value
- //
- // CrossedOut, characters legible, but
- // marked for deletion (9).
- CrossedOut(arg interface{}) Value
- // StrikeThrough is alias for the CrossedOut.
- StrikeThrough(arg interface{}) Value
- //
- // Framed (51).
- Framed(arg interface{}) Value
- // Encircled (52).
- Encircled(arg interface{}) Value
- //
- // Overlined (53).
- Overlined(arg interface{}) Value
-
- //
- // Foreground colors
- //
- //
- // Black foreground color (30)
- Black(arg interface{}) Value
- // Red foreground color (31)
- Red(arg interface{}) Value
- // Green foreground color (32)
- Green(arg interface{}) Value
- // Yellow foreground color (33)
- Yellow(arg interface{}) Value
- // Brown foreground color (33)
- //
- // Deprecated: use Yellow instead, following specification
- Brown(arg interface{}) Value
- // Blue foreground color (34)
- Blue(arg interface{}) Value
- // Magenta foreground color (35)
- Magenta(arg interface{}) Value
- // Cyan foreground color (36)
- Cyan(arg interface{}) Value
- // White foreground color (37)
- White(arg interface{}) Value
- //
- // Bright foreground colors
- //
- // BrightBlack foreground color (90)
- BrightBlack(arg interface{}) Value
- // BrightRed foreground color (91)
- BrightRed(arg interface{}) Value
- // BrightGreen foreground color (92)
- BrightGreen(arg interface{}) Value
- // BrightYellow foreground color (93)
- BrightYellow(arg interface{}) Value
- // BrightBlue foreground color (94)
- BrightBlue(arg interface{}) Value
- // BrightMagenta foreground color (95)
- BrightMagenta(arg interface{}) Value
- // BrightCyan foreground color (96)
- BrightCyan(arg interface{}) Value
- // BrightWhite foreground color (97)
- BrightWhite(arg interface{}) Value
- //
- // Other
- //
- // Index of pre-defined 8-bit foreground color
- // from 0 to 255 (38;5;n).
- //
- // 0- 7: standard colors (as in ESC [ 30–37 m)
- // 8- 15: high intensity colors (as in ESC [ 90–97 m)
- // 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
- // 232-255: grayscale from black to white in 24 steps
- //
- Index(n uint8, arg interface{}) Value
- // Gray from 0 to 23.
- Gray(n uint8, arg interface{}) Value
-
- //
- // Background colors
- //
- //
- // BgBlack background color (40)
- BgBlack(arg interface{}) Value
- // BgRed background color (41)
- BgRed(arg interface{}) Value
- // BgGreen background color (42)
- BgGreen(arg interface{}) Value
- // BgYellow background color (43)
- BgYellow(arg interface{}) Value
- // BgBrown background color (43)
- //
- // Deprecated: use BgYellow instead, following specification
- BgBrown(arg interface{}) Value
- // BgBlue background color (44)
- BgBlue(arg interface{}) Value
- // BgMagenta background color (45)
- BgMagenta(arg interface{}) Value
- // BgCyan background color (46)
- BgCyan(arg interface{}) Value
- // BgWhite background color (47)
- BgWhite(arg interface{}) Value
- //
- // Bright background colors
- //
- // BgBrightBlack background color (100)
- BgBrightBlack(arg interface{}) Value
- // BgBrightRed background color (101)
- BgBrightRed(arg interface{}) Value
- // BgBrightGreen background color (102)
- BgBrightGreen(arg interface{}) Value
- // BgBrightYellow background color (103)
- BgBrightYellow(arg interface{}) Value
- // BgBrightBlue background color (104)
- BgBrightBlue(arg interface{}) Value
- // BgBrightMagenta background color (105)
- BgBrightMagenta(arg interface{}) Value
- // BgBrightCyan background color (106)
- BgBrightCyan(arg interface{}) Value
- // BgBrightWhite background color (107)
- BgBrightWhite(arg interface{}) Value
- //
- // Other
- //
- // BgIndex of 8-bit pre-defined background color
- // from 0 to 255 (48;5;n).
- //
- // 0- 7: standard colors (as in ESC [ 40–47 m)
- // 8- 15: high intensity colors (as in ESC [100–107 m)
- // 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
- // 232-255: grayscale from black to white in 24 steps
- //
- BgIndex(n uint8, arg interface{}) Value
- // BgGray from 0 to 23.
- BgGray(n uint8, arg interface{}) Value
-
- //
- // Special
- //
- // Colorize removes existing colors and
- // formats of the argument and applies given.
- Colorize(arg interface{}, color Color) Value
-
- //
- // Support methods
- //
- // Sprintf allows to use colored format.
- Sprintf(format interface{}, args ...interface{}) string
+type Aurora struct {
+ conf Config
+ cc colorConfig
}
-// NewAurora returns a new Aurora interface that
-// will support or not support colors depending
-// the enableColors argument
-func NewAurora(enableColors bool) Aurora {
- if enableColors {
- return aurora{}
- }
- return auroraClear{}
-}
-
-// no colors
-
-type auroraClear struct{}
-
-func (auroraClear) Reset(arg interface{}) Value { return valueClear{arg} }
-
-func (auroraClear) Bold(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Faint(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) DoublyUnderline(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Fraktur(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Italic(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Underline(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) SlowBlink(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) RapidBlink(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Blink(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Reverse(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Inverse(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Conceal(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Hidden(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) CrossedOut(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) StrikeThrough(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Framed(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Encircled(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Overlined(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Black(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Red(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Green(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Yellow(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Brown(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Blue(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Magenta(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Cyan(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) White(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BrightBlack(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BrightRed(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BrightGreen(arg interface{}) Value {
- return valueClear{arg}
+// New returns new colorizer by given Options.
+func New(opts ...Option) (a *Aurora) {
+ a = new(Aurora)
+ a.conf = NewConfig() // set defaults
+ a.conf.Apply(opts...) // apply options
+ a.cc = a.conf.colorConfig() // keep the short hand
+ return
}
-func (auroraClear) BrightYellow(arg interface{}) Value {
- return valueClear{arg}
+// Config of the colorizer. It returns copy of the configurations.
+func (a *Aurora) Config() Config {
+ return a.conf
}
-func (auroraClear) BrightBlue(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BrightMagenta(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BrightCyan(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BrightWhite(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Index(_ uint8, arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) Gray(_ uint8, arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBlack(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgRed(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgGreen(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgYellow(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrown(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBlue(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgMagenta(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgCyan(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgWhite(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightBlack(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightRed(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightGreen(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightYellow(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightBlue(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightMagenta(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightCyan(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgBrightWhite(arg interface{}) Value {
- return valueClear{arg}
-}
-
-func (auroraClear) BgIndex(_ uint8, arg interface{}) Value {
- return valueClear{arg}
+// Reset wraps given argument returning Value without formats, colors and links.
+func (a *Aurora) Reset(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Reset()
+ }
+ return Value{
+ cc: a.cc,
+ value: arg,
+ }
}
-func (auroraClear) BgGray(_ uint8, arg interface{}) Value {
- return valueClear{arg}
+// Clear wraps given argument returning Value without formats and colors. But
+// preserving links.
+func (a *Aurora) Clear(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Clear()
+ }
+ return Value{
+ cc: a.cc,
+ value: arg,
+ }
}
-func (auroraClear) Colorize(arg interface{}, _ Color) Value {
- return valueClear{arg}
+// Formats
+//
+// Bold or increased intensity (1).
+func (a *Aurora) Bold(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Bold()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Bold()),
+ value: arg,
+ }
}
-func (auroraClear) Sprintf(format interface{}, args ...interface{}) string {
- if str, ok := format.(string); ok {
- return fmt.Sprintf(str, args...)
+// Faint, decreased intensity (2).
+func (a *Aurora) Faint(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Faint()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Faint()),
+ value: arg,
}
- return fmt.Sprintf(fmt.Sprint(format), args...)
}
-// colorized
-
-type aurora struct{}
-
-func (aurora) Reset(arg interface{}) Value {
- return Reset(arg)
+// DoublyUnderline or Bold off, double-underline per ECMA-48 (21).
+func (a *Aurora) DoublyUnderline(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.DoublyUnderline()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).DoublyUnderline()),
+ value: arg,
+ }
}
-func (aurora) Bold(arg interface{}) Value {
- return Bold(arg)
+// Fraktur, rarely supported (20).
+func (a *Aurora) Fraktur(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Fraktur()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Fraktur()),
+ value: arg,
+ }
}
-func (aurora) Faint(arg interface{}) Value {
- return Faint(arg)
+// Italic, not widely supported, sometimes treated as inverse (3).
+func (a *Aurora) Italic(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Italic()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Italic()),
+ value: arg,
+ }
}
-func (aurora) DoublyUnderline(arg interface{}) Value {
- return DoublyUnderline(arg)
+// Underline (4).
+func (a *Aurora) Underline(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Underline()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Underline()),
+ value: arg,
+ }
}
-func (aurora) Fraktur(arg interface{}) Value {
- return Fraktur(arg)
+// SlowBlink, blinking less than 150 per minute (5).
+func (a *Aurora) SlowBlink(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.SlowBlink()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).SlowBlink()),
+ value: arg,
+ }
}
-func (aurora) Italic(arg interface{}) Value {
- return Italic(arg)
+// RapidBlink, blinking 150+ per minute, not widely supported (6).
+func (a *Aurora) RapidBlink(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.RapidBlink()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).RapidBlink()),
+ value: arg,
+ }
}
-func (aurora) Underline(arg interface{}) Value {
- return Underline(arg)
+// Blink is alias for the SlowBlink.
+func (a *Aurora) Blink(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Blink()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Blink()),
+ value: arg,
+ }
}
-func (aurora) SlowBlink(arg interface{}) Value {
- return SlowBlink(arg)
+// Reverse video, swap foreground and background colors (7).
+func (a *Aurora) Reverse(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Reverse()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Reverse()),
+ value: arg,
+ }
}
-func (aurora) RapidBlink(arg interface{}) Value {
- return RapidBlink(arg)
+// Inverse is alias for the Reverse
+func (a *Aurora) Inverse(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Inverse()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Inverse()),
+ value: arg,
+ }
}
-func (aurora) Blink(arg interface{}) Value {
- return Blink(arg)
+// Conceal, hidden, not widely supported (8).
+func (a *Aurora) Conceal(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Conceal()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Conceal()),
+ value: arg,
+ }
}
-func (aurora) Reverse(arg interface{}) Value {
- return Reverse(arg)
+// Hidden is alias for the Conceal.
+func (a *Aurora) Hidden(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Hidden()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Hidden()),
+ value: arg,
+ }
}
-func (aurora) Inverse(arg interface{}) Value {
- return Inverse(arg)
+// CrossedOut, characters legible, but marked for deletion (9).
+func (a *Aurora) CrossedOut(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.CrossedOut()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).CrossedOut()),
+ value: arg,
+ }
}
-func (aurora) Conceal(arg interface{}) Value {
- return Conceal(arg)
+// StrikeThrough is alias for the CrossedOut.
+func (a *Aurora) StrikeThrough(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.StrikeThrough()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).StrikeThrough()),
+ value: arg,
+ }
}
-func (aurora) Hidden(arg interface{}) Value {
- return Hidden(arg)
+// Framed (51).
+func (a *Aurora) Framed(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Framed()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Framed()),
+ value: arg,
+ }
}
-func (aurora) CrossedOut(arg interface{}) Value {
- return CrossedOut(arg)
+// Encircled (52).
+func (a *Aurora) Encircled(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Encircled()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Encircled()),
+ value: arg,
+ }
}
-func (aurora) StrikeThrough(arg interface{}) Value {
- return StrikeThrough(arg)
+// Overlined (53).
+func (a *Aurora) Overlined(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Overlined()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Overlined()),
+ value: arg,
+ }
}
-func (aurora) Framed(arg interface{}) Value {
- return Framed(arg)
+// Foreground colors
+//
+// Black foreground color (30).
+func (a *Aurora) Black(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Black()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Black()),
+ value: arg,
+ }
}
-func (aurora) Encircled(arg interface{}) Value {
- return Encircled(arg)
+// Red foreground color (31).
+func (a *Aurora) Red(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Red()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Red()),
+ value: arg,
+ }
}
-func (aurora) Overlined(arg interface{}) Value {
- return Overlined(arg)
+// Green foreground color (32).
+func (a *Aurora) Green(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Green()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Green()),
+ value: arg,
+ }
}
-func (aurora) Black(arg interface{}) Value {
- return Black(arg)
+// Yellow foreground color (33).
+func (a *Aurora) Yellow(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Yellow()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Yellow()),
+ value: arg,
+ }
}
-func (aurora) Red(arg interface{}) Value {
- return Red(arg)
+// Blue foreground color (34).
+func (a *Aurora) Blue(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Blue()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Blue()),
+ value: arg,
+ }
}
-func (aurora) Green(arg interface{}) Value {
- return Green(arg)
+// Magenta foreground color (35).
+func (a *Aurora) Magenta(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Magenta()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Magenta()),
+ value: arg,
+ }
}
-func (aurora) Yellow(arg interface{}) Value {
- return Yellow(arg)
+// Cyan foreground color (36).
+func (a *Aurora) Cyan(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Cyan()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Cyan()),
+ value: arg,
+ }
}
-func (aurora) Brown(arg interface{}) Value {
- return Brown(arg)
+// White foreground color (37).
+func (a *Aurora) White(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.White()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).White()),
+ value: arg,
+ }
}
-func (aurora) Blue(arg interface{}) Value {
- return Blue(arg)
+// Bright foreground colors.
+//
+// BrightBlack foreground color (90).
+func (a *Aurora) BrightBlack(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightBlack()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightBlack()),
+ value: arg,
+ }
}
-func (aurora) Magenta(arg interface{}) Value {
- return Magenta(arg)
+// BrightRed foreground color (91).
+func (a *Aurora) BrightRed(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightRed()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightRed()),
+ value: arg,
+ }
}
-func (aurora) Cyan(arg interface{}) Value {
- return Cyan(arg)
+// BrightGreen foreground color (92).
+func (a *Aurora) BrightGreen(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightGreen()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightGreen()),
+ value: arg,
+ }
}
-func (aurora) White(arg interface{}) Value {
- return White(arg)
+// BrightYellow foreground color (93).
+func (a *Aurora) BrightYellow(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightYellow()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightYellow()),
+ value: arg,
+ }
}
-func (aurora) BrightBlack(arg interface{}) Value {
- return BrightBlack(arg)
+// BrightBlue foreground color (94).
+func (a *Aurora) BrightBlue(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightBlue()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightBlue()),
+ value: arg,
+ }
}
-func (aurora) BrightRed(arg interface{}) Value {
- return BrightRed(arg)
+// BrightMagenta foreground color (95).
+func (a *Aurora) BrightMagenta(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightMagenta()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightMagenta()),
+ value: arg,
+ }
}
-func (aurora) BrightGreen(arg interface{}) Value {
- return BrightGreen(arg)
+// BrightCyan foreground color (96).
+func (a *Aurora) BrightCyan(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightCyan()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightCyan()),
+ value: arg,
+ }
}
-func (aurora) BrightYellow(arg interface{}) Value {
- return BrightYellow(arg)
+// BrightWhite foreground color (97).
+func (a *Aurora) BrightWhite(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BrightWhite()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BrightWhite()),
+ value: arg,
+ }
}
-func (aurora) BrightBlue(arg interface{}) Value {
- return BrightBlue(arg)
+// Other colors.
+//
+// Index of pre-defined 8-bit foreground color from 0 to 255 (38;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 30–37 m)
+// 8- 15: high intensity colors (as in ESC [ 90–97 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func (a *Aurora) Index(n ColorIndex, arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Index(n)
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Index(n)),
+ value: arg,
+ }
}
-func (aurora) BrightMagenta(arg interface{}) Value {
- return BrightMagenta(arg)
+// Gray from 0 to 23.
+func (a *Aurora) Gray(n GrayIndex, arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Gray(n)
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).Gray(n)),
+ value: arg,
+ }
}
-func (aurora) BrightCyan(arg interface{}) Value {
- return BrightCyan(arg)
+// Background colors.
+//
+// BgBlack background color (40).
+func (a *Aurora) BgBlack(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBlack()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBlack()),
+ value: arg,
+ }
}
-func (aurora) BrightWhite(arg interface{}) Value {
- return BrightWhite(arg)
+// BgRed background color (41).
+func (a *Aurora) BgRed(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgRed()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgRed()),
+ value: arg,
+ }
}
-func (aurora) Index(index uint8, arg interface{}) Value {
- return Index(index, arg)
+// BgGreen background color (42).
+func (a *Aurora) BgGreen(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgGreen()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgGreen()),
+ value: arg,
+ }
}
-func (aurora) Gray(n uint8, arg interface{}) Value {
- return Gray(n, arg)
+// BgYellow background color (43).
+func (a *Aurora) BgYellow(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgYellow()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgYellow()),
+ value: arg,
+ }
}
-func (aurora) BgBlack(arg interface{}) Value {
- return BgBlack(arg)
+// BgBlue background color (44).
+func (a *Aurora) BgBlue(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBlue()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBlue()),
+ value: arg,
+ }
}
-func (aurora) BgRed(arg interface{}) Value {
- return BgRed(arg)
+// BgMagenta background color (45).
+func (a *Aurora) BgMagenta(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgMagenta()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgMagenta()),
+ value: arg,
+ }
}
-func (aurora) BgGreen(arg interface{}) Value {
- return BgGreen(arg)
+// BgCyan background color (46).
+func (a *Aurora) BgCyan(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgCyan()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgCyan()),
+ value: arg,
+ }
}
-func (aurora) BgYellow(arg interface{}) Value {
- return BgYellow(arg)
+// BgWhite background color (47).
+func (a *Aurora) BgWhite(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgWhite()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgWhite()),
+ value: arg,
+ }
}
-func (aurora) BgBrown(arg interface{}) Value {
- return BgBrown(arg)
+// Bright background colors.
+//
+// BgBrightBlack background color (100).
+func (a *Aurora) BgBrightBlack(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightBlack()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightBlack()),
+ value: arg,
+ }
}
-func (aurora) BgBlue(arg interface{}) Value {
- return BgBlue(arg)
+// BgBrightRed background color (101).
+func (a *Aurora) BgBrightRed(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightRed()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightRed()),
+ value: arg,
+ }
}
-func (aurora) BgMagenta(arg interface{}) Value {
- return BgMagenta(arg)
+// BgBrightGreen background color (102).
+func (a *Aurora) BgBrightGreen(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightGreen()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightGreen()),
+ value: arg,
+ }
}
-func (aurora) BgCyan(arg interface{}) Value {
- return BgCyan(arg)
+// BgBrightYellow background color (103).
+func (a *Aurora) BgBrightYellow(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightYellow()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightYellow()),
+ value: arg,
+ }
}
-func (aurora) BgWhite(arg interface{}) Value {
- return BgWhite(arg)
+// BgBrightBlue background color (104).
+func (a *Aurora) BgBrightBlue(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightBlue()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightBlue()),
+ value: arg,
+ }
}
-func (aurora) BgBrightBlack(arg interface{}) Value {
- return BgBrightBlack(arg)
+// BgBrightMagenta background color (105).
+func (a *Aurora) BgBrightMagenta(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightMagenta()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightMagenta()),
+ value: arg,
+ }
}
-func (aurora) BgBrightRed(arg interface{}) Value {
- return BgBrightRed(arg)
+// BgBrightCyan background color (106).
+func (a *Aurora) BgBrightCyan(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightCyan()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightCyan()),
+ value: arg,
+ }
}
-func (aurora) BgBrightGreen(arg interface{}) Value {
- return BgBrightGreen(arg)
+// BgBrightWhite background color (107).
+func (a *Aurora) BgBrightWhite(arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgBrightWhite()
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgBrightWhite()),
+ value: arg,
+ }
}
-func (aurora) BgBrightYellow(arg interface{}) Value {
- return BgBrightYellow(arg)
+// Other background colors.
+//
+// BgIndex of 8-bit pre-defined background color from 0 to 255 (48;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 40–47 m)
+// 8- 15: high intensity colors (as in ESC [100–107 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func (a *Aurora) BgIndex(n ColorIndex, arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgIndex(n)
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgIndex(n)),
+ value: arg,
+ }
}
-func (aurora) BgBrightBlue(arg interface{}) Value {
- return BgBrightBlue(arg)
+// BgGray from 0 to 23.
+func (a *Aurora) BgGray(n GrayIndex, arg interface{}) Value {
+ if val, ok := arg.(Value); ok {
+ return val.BgGray(n)
+ }
+ return Value{
+ cc: a.cc | colorConfig(Color(0).BgGray(n)),
+ value: arg,
+ }
}
-func (aurora) BgBrightMagenta(arg interface{}) Value {
- return BgBrightMagenta(arg)
+// Special color functions.
+//
+// Colorize removes existing colors and
+// formats of the argument and applies given.
+func (a *Aurora) Colorize(arg interface{}, color Color) Value {
+ if val, ok := arg.(Value); ok {
+ return val.Colorize(color)
+ }
+ return Value{
+ cc: a.cc | colorConfig(color),
+ value: arg,
+ }
}
-func (aurora) BgBrightCyan(arg interface{}) Value {
- return BgBrightCyan(arg)
-}
+// Hyperlinks feature
+//
+// Hyperlink with given target and parameters. If hyperlinks feature is
+// disabled, then the 'arg' argument dropped and the 'target' used instead
+// inheriting all colors and format from the 'arg' (if it's a Colored).
+//
+// See https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+// for details about the hyperlinks feature.
+//
+// The Hyperlink doesn't escape the target and the params. They should be
+// checked and escaped before.
+//
+// See also HyperlinkID function.
+//
+// For a simple example
+//
+// au.Hyperlink("Example", "http://example.com")
+//
+// and an example with ID
+//
+// au.Hyperlink("Example", "http://example.com", aurora.HyperlinkID("10"))
+func (a *Aurora) Hyperlink(arg interface{}, target string,
+ params ...HyperlinkParam) Value {
-func (aurora) BgBrightWhite(arg interface{}) Value {
- return BgBrightWhite(arg)
+ if val, ok := arg.(Value); ok {
+ return val.Hyperlink(target, params...)
+ }
+ return Value{
+ cc: a.cc,
+ value: arg,
+ }.Hyperlink(target, params...)
}
-func (aurora) BgIndex(n uint8, arg interface{}) Value {
- return BgIndex(n, arg)
+// HyperlinkTarget of the argument if it's a Value.
+func (a *Aurora) HyperlinkTarget(arg interface{}) (target string) {
+ if val, ok := arg.(Value); ok {
+ return val.HyperlinkTarget()
+ }
+ return // no target
}
-func (aurora) BgGray(n uint8, arg interface{}) Value {
- return BgGray(n, arg)
+// HyperlinkParams of the argument if it's a Value.
+func (a *Aurora) HyperlinkParams(arg interface{}) (params []HyperlinkParam) {
+ if val, ok := arg.(Value); ok {
+ return val.HyperlinkParams()
+ }
+ return // no target
}
-func (aurora) Colorize(arg interface{}, color Color) Value {
- return Colorize(arg, color)
+func (a *Aurora) transform(arg interface{}) (val Value, ok bool) {
+ var ai Value
+ ai, ok = arg.(Value)
+ if !ok {
+ return // Value{}, false
+ }
+ // if ai.cc.resetColor() == a.cc.resetColor() {
+ // return // don't replace, same configurations
+ // }
+ val = Value{cc: a.cc | colorConfig(ai.cc.color()), value: ai.value}
+ if a.cc.hyperlinksEnbaled() {
+ val.hyperlink = ai.hyperlink
+ }
+ return val, true // transformed value, true
}
-func (aurora) Sprintf(format interface{}, args ...interface{}) string {
- return Sprintf(format, args...)
+// Sprintf allows to use Value as format. For example
+//
+// var v = Sprintf(Red("total: +3.5f points"), Blue(3.14))
+//
+// In this case "total:" and "points" will be red, but
+// 3.14 will be blue. But, in another example
+//
+// var v = Sprintf(Red("total: +3.5f points"), 3.14)
+//
+// full string will be red. And no way to clear 3.14 to default format and
+// color.
+//
+// It applies own configurations to all given Values.
+func (a *Aurora) Sprintf(format interface{}, args ...interface{}) string {
+ // // clear colors & links as configured by the a
+ if f, ok := a.transform(format); ok {
+ format = f
+ }
+ for i := range args {
+ if ax, ok := a.transform(args[i]); ok {
+ args[i] = ax
+ }
+ }
+ return sprintf(format, args...)
}
diff --git a/aurora_hyperlinks.gif b/aurora_hyperlinks.gif
new file mode 100644
index 0000000..03054de
Binary files /dev/null and b/aurora_hyperlinks.gif differ
diff --git a/aurora_hyperlinks.webm b/aurora_hyperlinks.webm
new file mode 100644
index 0000000..1ec190b
Binary files /dev/null and b/aurora_hyperlinks.webm differ
diff --git a/aurora_hyperlinks_flags.png b/aurora_hyperlinks_flags.png
new file mode 100644
index 0000000..a1c6f40
Binary files /dev/null and b/aurora_hyperlinks_flags.png differ
diff --git a/aurora_test.go b/aurora_test.go
index 158e639..8a841eb 100644
--- a/aurora_test.go
+++ b/aurora_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -37,45 +37,48 @@ package aurora
import (
"testing"
-)
-func isClear(v Value) bool {
- return v.Color() == 0 && v.tail() == 0
-}
+ "github.com/stretchr/testify/assert"
+)
func isColor(v Value, clr Color) bool {
return v.Color() == clr
}
-func isTail(v Value, tl Color) bool {
- return v.tail() == tl
+func Test_New(t *testing.T) {
+ var (
+ dconf = NewConfig() // default configurations
+ a = New()
+ )
+ assert.Equal(t, dconf, a.conf, "non-default configurations")
+ // options
+ a = New(WithColors(true), WithHyperlinks(true))
+ assert.True(t, a.conf.Colors)
+ assert.True(t, a.conf.Hyperlinks)
+ // colors
+ a = New(WithColors(false), WithHyperlinks(false))
+ assert.False(t, a.conf.Colors)
+ assert.False(t, a.conf.Hyperlinks)
+
}
-func Test_NewAurora(t *testing.T) {
- if a := NewAurora(false); a == nil {
- t.Error("NewAurora(false) returns nil")
- }
- if a := NewAurora(true); a == nil {
- t.Error("NewAurora(true) returns nil")
- }
- if t.Failed() {
- t.FailNow()
- }
+func TestAurora_Config(t *testing.T) {
+ assert.Equal(t, NewConfig(), New().Config())
}
-func Test_auroraClear_methods(t *testing.T) {
- a := NewAurora(false)
- test := func(mn string, v Value) {
- if !isClear(v) {
- t.Errorf("NewAurora(false).%s is not clear", mn)
- } else if str, ok := v.Value().(string); !ok {
- t.Errorf("NewAurora(false).%s wrong value type", mn)
- } else if str != "x" {
- t.Errorf("NewAurora(false).%s wrong value", mn)
- }
+func TestAurora_no_colors(t *testing.T) {
+
+ var a = New(WithColors(false), WithHyperlinks(false))
+
+ var test = func(mn string, v Value) {
+ t.Helper()
+ t.Log(mn)
+ assert.Zero(t, v.Color(), "colored")
+ assert.Equal(t, "x", v.Value(), "wrong value")
}
test("Reset", a.Reset("x"))
+ test("Clear", a.Clear("x"))
test("Bold", a.Bold("x"))
test("Faint", a.Faint("x"))
@@ -100,7 +103,6 @@ func Test_auroraClear_methods(t *testing.T) {
test("Red", a.Red("x"))
test("Green", a.Green("x"))
test("Yellow", a.Yellow("x"))
- test("Brown", a.Brown("x"))
test("Blue", a.Blue("x"))
test("Magenta", a.Magenta("x"))
test("Cyan", a.Cyan("x"))
@@ -120,7 +122,6 @@ func Test_auroraClear_methods(t *testing.T) {
test("BgRed", a.BgRed("x"))
test("BgGreen", a.BgGreen("x"))
test("BgYellow", a.BgYellow("x"))
- test("BgBrown", a.BgBrown("x"))
test("BgBlue", a.BgBlue("x"))
test("BgMagenta", a.BgMagenta("x"))
test("BgCyan", a.BgCyan("x"))
@@ -140,29 +141,21 @@ func Test_auroraClear_methods(t *testing.T) {
}
-func Test_auroraClear_sprintf(t *testing.T) {
- a := NewAurora(false)
- if s := a.Sprintf(a.Black("x: %d"), a.Blue(2)); s != "x: 2" {
- t.Error("NewAurora(false).Sprintf wrong value")
- }
- if s := a.Sprintf("x: %d", a.Blue(2)); s != "x: 2" {
- t.Error("NewAurora(false).Sprintf wrong value")
- }
+func Test_noColors_sprintf(t *testing.T) {
+ var au = New(WithColors(false))
+ assert.Equal(t, "x: 2", au.Sprintf(au.Black("x: %d"), au.Blue(2)))
+ assert.Equal(t, "x: 2", au.Sprintf("x: %d", au.Blue(2)))
}
-func Test_aurora_methods(t *testing.T) {
- a := NewAurora(true)
- test := func(mn string, v Value, clr Color) {
+func TestAurora_colored(t *testing.T) {
+
+ var a = New() // with colors, with hyperlinks
+
+ var test = func(mn string, v Value, clr Color) {
t.Helper()
- if !isColor(v, clr) {
- t.Errorf("NewAurora(true).%s wrong color: %d", mn, v.Color())
- } else if !isTail(v, 0) {
- t.Errorf("NewAurora(true).%s unexpected tail value", mn)
- } else if str, ok := v.Value().(string); !ok {
- t.Errorf("NewAurora(true).%s wrong value type", mn)
- } else if str != "x" {
- t.Errorf("NewAurora(true).%s wrong value", mn)
- }
+ t.Log(mn)
+ assert.Equal(t, clr, v.Color())
+ assert.Equal(t, "x", v.Value(), "wrong value")
}
test("Reset", a.Reset("x"), 0)
@@ -189,7 +182,6 @@ func Test_aurora_methods(t *testing.T) {
test("Red", a.Red("x"), RedFg)
test("Green", a.Green("x"), GreenFg)
test("Yellow", a.Yellow("x"), YellowFg)
- test("Brown", a.Brown("x"), BrownFg)
test("Blue", a.Blue("x"), BlueFg)
test("Magenta", a.Magenta("x"), MagentaFg)
test("Cyan", a.Cyan("x"), CyanFg)
@@ -209,7 +201,6 @@ func Test_aurora_methods(t *testing.T) {
test("BgRed", a.BgRed("x"), RedBg)
test("BgGreen", a.BgGreen("x"), GreenBg)
test("BgYellow", a.BgYellow("x"), YellowBg)
- test("BgBrown", a.BgBrown("x"), BrownBg)
test("BgBlue", a.BgBlue("x"), BlueBg)
test("BgMagenta", a.BgMagenta("x"), MagentaBg)
test("BgCyan", a.BgCyan("x"), CyanBg)
@@ -229,14 +220,10 @@ func Test_aurora_methods(t *testing.T) {
RedFg|BlueBg|BrightBg|BoldFm)
}
-func Test_aurora_Sprintf(t *testing.T) {
- a := NewAurora(true)
- s := a.Sprintf(a.Black("x: %dB"), a.Blue(2))
- if s != "\033[30mx: \033[0;34m2\033[0;30mB\033[0m" {
- t.Errorf("NewAurora(true).Sprintf wrong value: %q", s)
- }
- s = a.Sprintf("x: %dB", a.Blue(2))
- if s != "x: \033[34m2\033[0mB" {
- t.Errorf("NewAurora(true).Sprintf wrong value: %q", s)
- }
+func TestAurora_Sprintf(t *testing.T) {
+ var a = New()
+ assert.Equal(t, "\033[30mx: \033[0;34m2\033[0;30mB\033[0m",
+ a.Sprintf(a.Black("x: %dB"), a.Blue(2)))
+ assert.Equal(t, "x: \033[34m2\033[0mB",
+ a.Sprintf("x: %dB", a.Blue(2)))
}
diff --git a/bench_test.go b/bench_test.go
index e30cb9a..1cc60c0 100644
--- a/bench_test.go
+++ b/bench_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -54,7 +54,7 @@ var (
)
// 18 values
-func simpleValues(a Aurora, x string) []Value {
+func simpleValues(a *Aurora, x string) []Value {
return []Value{
a.Reset("x"),
@@ -81,7 +81,7 @@ func simpleValues(a Aurora, x string) []Value {
a.Red("x"),
a.Green("x"),
a.Yellow("x"),
- a.Brown("x"),
+ a.Yellow("x"),
a.Blue("x"),
a.Magenta("x"),
a.Cyan("x"),
@@ -101,7 +101,7 @@ func simpleValues(a Aurora, x string) []Value {
a.BgRed("x"),
a.BgGreen("x"),
a.BgYellow("x"),
- a.BgBrown("x"),
+ a.BgYellow("x"),
a.BgBlue("x"),
a.BgMagenta("x"),
a.BgCyan("x"),
@@ -120,7 +120,7 @@ func simpleValues(a Aurora, x string) []Value {
}
// 18 values
-func complexValues(a Aurora, x string) []Value {
+func complexValues(a *Aurora, x string) []Value {
var allFormats = func(val Value) Value {
return val.Bold().DoublyUnderline().Fraktur().Blink().Italic().
@@ -155,7 +155,7 @@ func complexValues(a Aurora, x string) []Value {
allFormats(a.Red(x).BgBrightRed()),
allFormats(a.Green(x).BgBrightRed()),
allFormats(a.Yellow(x).BgBrightRed()),
- allFormats(a.Brown(x).BgBrightRed()),
+ allFormats(a.Yellow(x).BgBrightRed()),
allFormats(a.Blue(x).BgBrightRed()),
allFormats(a.Magenta(x).BgBrightRed()),
allFormats(a.Cyan(x).BgBrightRed()),
@@ -175,7 +175,7 @@ func complexValues(a Aurora, x string) []Value {
allFormats(a.BgRed(x).BrightRed()),
allFormats(a.BgGreen(x).BrightGreen()),
allFormats(a.BgYellow(x).BrightYellow()),
- allFormats(a.BgBrown(x).BrightYellow()),
+ allFormats(a.BgYellow(x).BrightYellow()),
allFormats(a.BgBlue(x).BrightBlue()),
allFormats(a.BgMagenta(x).BrightMagenta()),
allFormats(a.BgCyan(x).BrightCyan()),
@@ -193,7 +193,7 @@ func complexValues(a Aurora, x string) []Value {
}
}
-func benchSimpleValue(b *testing.B, a Aurora, x string) {
+func benchSimpleValue(b *testing.B, a *Aurora, x string) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
gVals = simpleValues(a, x)
@@ -201,7 +201,7 @@ func benchSimpleValue(b *testing.B, a Aurora, x string) {
b.ReportAllocs()
}
-func benchComplexValue(b *testing.B, a Aurora, x string) {
+func benchComplexValue(b *testing.B, a *Aurora, x string) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
gVals = complexValues(a, x)
@@ -212,14 +212,14 @@ func benchComplexValue(b *testing.B, a Aurora, x string) {
func benchValueString(b *testing.B, vals []Value) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
- for j := 0; j < len(vals); j++ { // TODO: range and allocs ?
+ for j := 0; j < len(vals); j++ {
gStr = vals[j].String()
}
}
b.ReportAllocs()
}
-func benchSprintf(b *testing.B, a Aurora, format interface{},
+func benchSprintf(b *testing.B, a *Aurora, format interface{},
args ...interface{}) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -236,7 +236,7 @@ func toInterfaces(vals []Value) []interface{} {
return r
}
-func auroraBench(a Aurora, b *testing.B) {
+func auroraBench(a *Aurora, b *testing.B) {
// a.Red("...")
b.Run("simple value", func(b *testing.B) {
b.Run("short", func(b *testing.B) { benchSimpleValue(b, a, short) })
@@ -377,13 +377,13 @@ func auroraBench(a Aurora, b *testing.B) {
}
func Benchmark_auroraClear(b *testing.B) {
- a := NewAurora(false)
+ var a = New(WithColors(false), WithHyperlinks(false))
auroraBench(a, b)
}
// create a value
func Benchmark_aurora(b *testing.B) {
- a := NewAurora(true)
+ var a = New()
auroraBench(a, b)
}
@@ -419,7 +419,7 @@ func Benchmark_wrap(b *testing.B) {
{"Red", Red},
{"Green", Green},
{"Yellow", Yellow},
- {"Brown", Brown},
+ {"Yellow", Yellow},
{"Blue", Blue},
{"Magenta", Magenta},
{"Cyan", Cyan},
@@ -437,7 +437,7 @@ func Benchmark_wrap(b *testing.B) {
{"BgRed", BgRed},
{"BgGreen", BgGreen},
{"BgYellow", BgYellow},
- {"BgBrown", BgBrown},
+ {"BgYellow", BgYellow},
{"BgBlue", BgBlue},
{"BgMagenta", BgMagenta},
{"BgCyan", BgCyan},
diff --git a/color.go b/color.go
index 486fb67..d699159 100644
--- a/color.go
+++ b/color.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -45,7 +45,7 @@ type Color uint
Developer note.
- The int type is architecture depended and can be
+ The uint type is architecture depended and can be
represented as int32 or int64.
Thus, we can use 32-bits only to be fast and
@@ -112,7 +112,7 @@ const (
// 8 bits
// [ 0; 7] - 30-37
- // [ 8; 15] - 90-97
+ // [ 8; 15] - 90-97 bright
// [ 16; 231] - RGB
// [232; 255] - grayscale
@@ -132,11 +132,6 @@ const (
// 5 bits
- // BrownFg represents brown foreground color.
- //
- // Deprecated: use YellowFg instead, following specifications
- BrownFg = YellowFg
-
//
maskFg = (0xff << shiftFg) | flagFg
)
@@ -147,7 +142,7 @@ const (
// 8 bits
// [ 0; 7] - 40-47
- // [ 8; 15] - 100-107
+ // [ 8; 15] - 100-107 bright
// [ 16; 231] - RGB
// [232; 255] - grayscale
@@ -167,11 +162,6 @@ const (
// 5 bits
- // BrownBg represents brown foreground color.
- //
- // Deprecated: use YellowBg instead, following specifications
- BrownBg = YellowBg
-
//
maskBg = (0xff << shiftBg) | flagBg
)
@@ -182,13 +172,6 @@ const (
clear = esc + "0m"
)
-// IsValid returns true always
-//
-// Deprecated: don't use this method anymore
-func (c Color) IsValid() bool {
- return true
-}
-
// Nos returns string like 1;7;31;45. It
// may be an empty string for empty color.
// If the zero is true, then the string
@@ -396,3 +379,335 @@ func (c Color) appendNos(bs []byte, zero bool) []byte {
return bs
}
+
+// ColorIndex is index of pre-defined 8-bit foreground or
+// background colors from 0 to 255 (38;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 30–37 m)
+// 8- 15: high intensity colors (as in ESC [ 90–97 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+type ColorIndex uint8
+
+// GrayIndex from 0 to 23.
+type GrayIndex uint8
+
+// The Colored interface represents a value with a Color.
+type Colored interface {
+ Color() Color // color of the value
+}
+
+// Reset returns Color without a color and formats.
+func (c Color) Reset() Color {
+ return Color(0)
+}
+
+//
+// Formats
+//
+
+// Bold or increased intensity (1).
+func (c Color) Bold() Color {
+ return (c &^ FaintFm) | BoldFm
+}
+
+// Faint, decreased intensity (2).
+func (c Color) Faint() Color {
+ return (c &^ BoldFm) | FaintFm
+}
+
+// DoublyUnderline or Bold off, double-underline
+// per ECMA-48 (21).
+func (c Color) DoublyUnderline() Color {
+ return (c &^ UnderlineFm) | DoublyUnderlineFm
+}
+
+// Fraktur, rarely supported (20).
+func (c Color) Fraktur() Color {
+ return c | FrakturFm
+}
+
+// Italic, not widely supported, sometimes
+// treated as inverse (3).
+func (c Color) Italic() Color {
+ return c | ItalicFm
+}
+
+// Underline (4).
+func (c Color) Underline() Color {
+ return (c &^ DoublyUnderlineFm) | UnderlineFm
+}
+
+// SlowBlink, blinking less than 150
+// per minute (5).
+func (c Color) SlowBlink() Color {
+ return (c &^ RapidBlinkFm) | SlowBlinkFm
+}
+
+// RapidBlink, blinking 150+ per minute,
+// not widely supported (6).
+func (c Color) RapidBlink() Color {
+ return (c &^ SlowBlinkFm) | RapidBlinkFm
+}
+
+// Blink is alias for the SlowBlink.
+func (c Color) Blink() Color {
+ return c.SlowBlink()
+}
+
+// Reverse video, swap foreground and
+// background colors (7).
+func (c Color) Reverse() Color {
+ return c | ReverseFm
+}
+
+// Inverse is alias for the Reverse
+func (c Color) Inverse() Color {
+ return c.Reverse()
+}
+
+// Conceal, hidden, not widely supported (8).
+func (c Color) Conceal() Color {
+ return c | ConcealFm
+}
+
+// Hidden is alias for the Conceal
+func (c Color) Hidden() Color {
+ return c.Conceal()
+}
+
+// CrossedOut, characters legible, but
+// marked for deletion (9).
+func (c Color) CrossedOut() Color {
+ return c | CrossedOutFm
+}
+
+// StrikeThrough is alias for the CrossedOut.
+func (c Color) StrikeThrough() Color {
+ return c.CrossedOut()
+}
+
+// Framed (51).
+func (c Color) Framed() Color {
+ return c | FramedFm
+}
+
+// Encircled (52).
+func (c Color) Encircled() Color {
+ return c | EncircledFm
+}
+
+// Overlined (53).
+func (c Color) Overlined() Color {
+ return c | OverlinedFm
+}
+
+// Foreground colors
+//
+// Black foreground color (30)
+func (c Color) Black() Color {
+ return (c &^ maskFg) | BlackFg
+}
+
+// Red foreground color (31)
+func (c Color) Red() Color {
+ return (c &^ maskFg) | RedFg
+}
+
+// Green foreground color (32)
+func (c Color) Green() Color {
+ return (c &^ maskFg) | GreenFg
+}
+
+// Yellow foreground color (33)
+func (c Color) Yellow() Color {
+ return (c &^ maskFg) | YellowFg
+}
+
+// Blue foreground color (34)
+func (c Color) Blue() Color {
+ return (c &^ maskFg) | BlueFg
+}
+
+// Magenta foreground color (35)
+func (c Color) Magenta() Color {
+ return (c &^ maskFg) | MagentaFg
+}
+
+// Cyan foreground color (36)
+func (c Color) Cyan() Color {
+ return (c &^ maskFg) | CyanFg
+}
+
+// White foreground color (37)
+func (c Color) White() Color {
+ return (c &^ maskFg) | WhiteFg
+}
+
+// Bright foreground colors
+//
+// BrightBlack foreground color (90)
+func (c Color) BrightBlack() Color {
+ return (c &^ maskFg) | BrightFg | BlackFg
+}
+
+// BrightRed foreground color (91)
+func (c Color) BrightRed() Color {
+ return (c &^ maskFg) | BrightFg | RedFg
+}
+
+// BrightGreen foreground color (92)
+func (c Color) BrightGreen() Color {
+ return (c &^ maskFg) | BrightFg | GreenFg
+}
+
+// BrightYellow foreground color (93)
+func (c Color) BrightYellow() Color {
+ return (c &^ maskFg) | BrightFg | YellowFg
+}
+
+// BrightBlue foreground color (94)
+func (c Color) BrightBlue() Color {
+ return (c &^ maskFg) | BrightFg | BlueFg
+}
+
+// BrightMagenta foreground color (95)
+func (c Color) BrightMagenta() Color {
+ return (c &^ maskFg) | BrightFg | MagentaFg
+}
+
+// BrightCyan foreground color (96)
+func (c Color) BrightCyan() Color {
+ return (c &^ maskFg) | BrightFg | CyanFg
+}
+
+// BrightWhite foreground color (97)
+func (c Color) BrightWhite() Color {
+ return (c &^ maskFg) | BrightFg | WhiteFg
+}
+
+// Other
+//
+// Index of pre-defined 8-bit foreground color
+// from 0 to 255 (38;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 30–37 m)
+// 8- 15: high intensity colors (as in ESC [ 90–97 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func (c Color) Index(ci ColorIndex) Color {
+ return (c &^ maskFg) | (Color(ci) << shiftFg) | flagFg
+}
+
+// Gray from 0 to 23.
+func (c Color) Gray(n GrayIndex) Color {
+ if n > 23 {
+ n = 23
+ }
+ return (c &^ maskFg) | (Color(232+n) << shiftFg) | flagFg
+}
+
+// Background colors
+//
+// BgBlack background color (40)
+func (c Color) BgBlack() Color {
+ return (c &^ maskBg) | BlackBg
+}
+
+// BgRed background color (41)
+func (c Color) BgRed() Color {
+ return (c &^ maskBg) | RedBg
+}
+
+// BgGreen background color (42)
+func (c Color) BgGreen() Color {
+ return (c &^ maskBg) | GreenBg
+}
+
+// BgYellow background color (43)
+func (c Color) BgYellow() Color {
+ return (c &^ maskBg) | YellowBg
+}
+
+// BgBlue background color (44)
+func (c Color) BgBlue() Color {
+ return (c &^ maskBg) | BlueBg
+}
+
+// BgMagenta background color (45)
+func (c Color) BgMagenta() Color {
+ return (c &^ maskBg) | MagentaBg
+}
+
+// BgCyan background color (46)
+func (c Color) BgCyan() Color {
+ return (c &^ maskBg) | CyanBg
+}
+
+// BgWhite background color (47)
+func (c Color) BgWhite() Color {
+ return (c &^ maskBg) | WhiteBg
+}
+
+// Bright background colors
+//
+// BgBrightBlack background color (100)
+func (c Color) BgBrightBlack() Color {
+ return (c &^ maskBg) | BrightBg | BlackBg
+}
+
+// BgBrightRed background color (101)
+func (c Color) BgBrightRed() Color {
+ return (c &^ maskBg) | BrightBg | RedBg
+}
+
+// BgBrightGreen background color (102)
+func (c Color) BgBrightGreen() Color {
+ return (c &^ maskBg) | BrightBg | GreenBg
+}
+
+// BgBrightYellow background color (103)
+func (c Color) BgBrightYellow() Color {
+ return (c &^ maskBg) | BrightBg | YellowBg
+}
+
+// BgBrightBlue background color (104)
+func (c Color) BgBrightBlue() Color {
+ return (c &^ maskBg) | BrightBg | BlueBg
+}
+
+// BgBrightMagenta background color (105)
+func (c Color) BgBrightMagenta() Color {
+ return (c &^ maskBg) | BrightBg | MagentaBg
+}
+
+// BgBrightCyan background color (106)
+func (c Color) BgBrightCyan() Color {
+ return (c &^ maskBg) | BrightBg | CyanBg
+}
+
+// BgBrightWhite background color (107)
+func (c Color) BgBrightWhite() Color {
+ return (c &^ maskBg) | BrightBg | WhiteBg
+}
+
+// Other
+//
+// BgIndex of 8-bit pre-defined background color
+// from 0 to 255 (48;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 40–47 m)
+// 8- 15: high intensity colors (as in ESC [100–107 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func (c Color) BgIndex(n ColorIndex) Color {
+ return (c &^ maskBg) | (Color(n) << shiftBg) | flagBg
+}
+
+// BgGray from 0 to 23.
+func (c Color) BgGray(n GrayIndex) Color {
+ if n > 23 {
+ n = 23
+ }
+ return (c &^ maskBg) | (Color(232+n) << shiftBg) | flagBg
+}
diff --git a/color_test.go b/color_test.go
index d25ab7a..523ee96 100644
--- a/color_test.go
+++ b/color_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -36,8 +36,11 @@
package aurora
import (
+ "math"
"strconv"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestColor_Nos(t *testing.T) {
@@ -142,24 +145,337 @@ func TestColor_Nos(t *testing.T) {
want = "0"
}
}
- if nos != want {
- t.Errorf("%t %d: wrong nos string %q, want %q",
- zero, i, nos, want)
- }
+ assert.Equalf(t, want, nos, "%t %d: wrong nos string %q, want %q",
+ zero, i, nos, want)
}
}
}
-func TestColor_IsValid(t *testing.T) {
- if Color(0).IsValid() == false {
- t.Error("invalid")
+func Test_itoa(t *testing.T) {
+ for i := 0; i < 256; i++ {
+ var a = itoa(byte(i))
+ assert.Equalf(t, a, strconv.Itoa(i), "wrong %q, want %d", a, i)
}
}
-func Test_itoa(t *testing.T) {
+func TestColor_Reset(t *testing.T) {
+ var c Color = math.MaxUint // all bits set to 1
+ assert.Zero(t, c.Reset())
+}
+
+func TestColor_Bold(t *testing.T) {
+ assert.True(t, Color(0).Bold()&BoldFm != 0, "not a bold")
+ assert.True(t, Color(FaintFm).Bold()&FaintFm == 0, "contains faint")
+}
+
+func TestColor_Faint(t *testing.T) {
+ assert.True(t, Color(0).Faint()&FaintFm != 0, "not a faint")
+ assert.True(t, Color(BoldFm).Faint()&BoldFm == 0, "contains bold")
+}
+
+func TestColor_DoublyUnderline(t *testing.T) {
+ assert.True(t, Color(0).DoublyUnderline()&DoublyUnderlineFm != 0,
+ "not a doubly-underlined")
+ assert.True(t, Color(UnderlineFm).DoublyUnderline()&UnderlineFm == 0,
+ "contains underline")
+}
+
+func TestColor_Fraktur(t *testing.T) {
+ assert.True(t, Color(0).Fraktur()&FrakturFm != 0, "not a fraktur")
+}
+
+func TestColor_Italic(t *testing.T) {
+ assert.True(t, Color(0).Italic()&ItalicFm != 0, "not a italic")
+}
+
+func TestColor_Underline(t *testing.T) {
+ assert.True(t, Color(0).Underline()&UnderlineFm != 0, "not a underlined")
+}
+
+func TestColor_SlowBlink(t *testing.T) {
+ assert.True(t, Color(0).SlowBlink()&SlowBlinkFm != 0, "not a slow blinking")
+}
+
+func TestColor_RapidBlink(t *testing.T) {
+ assert.True(t, Color(0).RapidBlink()&RapidBlinkFm != 0,
+ "not a rapid blinking")
+}
+
+func TestColor_Blink(t *testing.T) {
+ assert.True(t, Color(0).Blink()&BlinkFm != 0, "not a blinking")
+}
+
+func TestColor_Reverse(t *testing.T) {
+ assert.True(t, Color(0).Reverse()&ReverseFm != 0, "not a reversed")
+}
+
+func TestColor_Inverse(t *testing.T) {
+ assert.True(t, Color(0).Inverse()&InverseFm != 0, "not a inversed")
+}
+
+func TestColor_Conceal(t *testing.T) {
+ assert.True(t, Color(0).Conceal()&ConcealFm != 0, "not a concealed")
+}
+
+func TestColor_Hidden(t *testing.T) {
+ assert.True(t, Color(0).Hidden()&HiddenFm != 0, "not a hidden")
+}
+
+func TestColor_CrossedOut(t *testing.T) {
+ assert.True(t, Color(0).CrossedOut()&CrossedOutFm != 0, "not a crossed out")
+}
+
+func TestColor_StrikeThrough(t *testing.T) {
+ assert.True(t, Color(0).StrikeThrough()&StrikeThroughFm != 0,
+ "not a striked through")
+}
+
+func TestColor_Framed(t *testing.T) {
+ assert.True(t, Color(0).Framed()&FramedFm != 0, "not a framed")
+}
+
+func TestColor_Encircled(t *testing.T) {
+ assert.True(t, Color(0).Encircled()&EncircledFm != 0, "not a encircled")
+}
+
+func TestColor_Overlined(t *testing.T) {
+ assert.True(t, Color(0).Overlined()&OverlinedFm != 0, "not a overlined")
+}
+
+func TestColor_Black(t *testing.T) {
+ assert.True(t, Color(0).Black()&BlackFg != 0, "not a black")
+ assert.True(t, Color(RedFg).Black()&RedFg == flagFg, "contains red")
+}
+
+func TestColor_Red(t *testing.T) {
+ assert.True(t, Color(0).Red()&RedFg != 0, "not a red")
+ assert.True(t, Color(BlackFg).Red()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_Green(t *testing.T) {
+ assert.True(t, Color(0).Green()&GreenFg != 0, "not a green")
+ assert.True(t, Color(BlackFg).Green()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_Yellow(t *testing.T) {
+ assert.True(t, Color(0).Yellow()&YellowFg != 0, "not a yellow")
+ assert.True(t, Color(BlackFg).Yellow()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_Blue(t *testing.T) {
+ assert.True(t, Color(0).Blue()&BlueFg != 0, "not a blue")
+ assert.True(t, Color(BlackFg).Blue()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_Magenta(t *testing.T) {
+ assert.True(t, Color(0).Magenta()&MagentaFg != 0, "not a magenta")
+ assert.True(t, Color(BlackFg).Magenta()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_Cyan(t *testing.T) {
+ assert.True(t, Color(0).Cyan()&CyanFg != 0, "not a cyan")
+ assert.True(t, Color(BlackFg).Cyan()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_White(t *testing.T) {
+ assert.True(t, Color(0).White()&WhiteFg != 0, "not a white")
+ assert.True(t, Color(BlackFg).White()&BlackFg == flagFg, "contains black")
+}
+
+func TestColor_BrightBlack(t *testing.T) {
+ assert.True(t, Color(0).BrightBlack()&(BrightFg|BlackFg) != 0,
+ "not a bright black")
+ assert.True(t, Color(RedFg).BrightBlack()&RedFg == flagFg, "contains red")
+}
+
+func TestColor_BrightRed(t *testing.T) {
+ assert.True(t, Color(0).BrightRed()&(BrightFg|RedFg) != 0,
+ "not a bright red")
+ assert.True(t, Color(BlackFg).BrightRed()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_BrightGreen(t *testing.T) {
+ assert.True(t, Color(0).BrightGreen()&(BrightFg|GreenFg) != 0,
+ "not a bright green")
+ assert.True(t, Color(BlackFg).BrightGreen()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_BrightYellow(t *testing.T) {
+ assert.True(t, Color(0).BrightYellow()&(BrightFg|YellowFg) != 0,
+ "not a bright yellow")
+ assert.True(t, Color(BlackFg).BrightYellow()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_BrightBlue(t *testing.T) {
+ assert.True(t, Color(0).BrightBlue()&(BrightFg|BlueFg) != 0,
+ "not a bright blue")
+ assert.True(t, Color(BlackFg).BrightBlue()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_BrightMagenta(t *testing.T) {
+ assert.True(t, Color(0).BrightMagenta()&(BrightFg|MagentaFg) != 0,
+ "not a bright blue")
+ assert.True(t, Color(BlackFg).BrightMagenta()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_BrightCyan(t *testing.T) {
+ assert.True(t, Color(0).BrightCyan()&(BrightFg|CyanFg) != 0,
+ "not a bright cyan")
+ assert.True(t, Color(BlackFg).BrightCyan()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_BrightWhite(t *testing.T) {
+ assert.True(t, Color(0).BrightWhite()&(BrightFg|WhiteFg) != 0,
+ "not a bright white")
+ assert.True(t, Color(BlackFg).BrightWhite()&BlackFg == flagFg,
+ "contains black")
+}
+
+func TestColor_Index(t *testing.T) {
for i := 0; i < 256; i++ {
- if a := itoa(byte(i)); a != strconv.Itoa(i) {
- t.Errorf("wrong %q, want %d", a, i)
- }
+ var ci = ColorIndex(i)
+ assert.Truef(t, Color(0).Index(ci)&flagFg != 0,
+ "missing indexed color, color index %d", i)
+ assert.Truef(t, Color(BlackFg).Index(ci)&BlackFg == flagFg,
+ "contains black, color index %d", i)
+ }
+}
+
+func TestColor_Gray(t *testing.T) {
+ for i := GrayIndex(0); i < 25; i++ {
+ assert.Truef(t, Color(0).Gray(i)&flagFg != 0,
+ "missing indexed gray color, gray index %d", i)
+ assert.Truef(t, Color(BlackFg).Gray(i)&BlackFg == flagFg,
+ "contains black, gray index %d", i)
+ }
+}
+
+func TestColor_BgBlack(t *testing.T) {
+ assert.True(t, Color(0).BgBlack()&BlackBg != 0, "not a black background")
+ assert.True(t, Color(RedBg).BgBlack()&RedBg == flagBg,
+ "contains red background")
+}
+
+func TestColor_BgRed(t *testing.T) {
+ assert.True(t, Color(0).BgRed()&RedBg != 0, "not a red background")
+ assert.True(t, Color(BlackBg).BgRed()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgGreen(t *testing.T) {
+ assert.True(t, Color(0).BgGreen()&GreenBg != 0, "not a green background")
+ assert.True(t, Color(BlackBg).BgGreen()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgYellow(t *testing.T) {
+ assert.True(t, Color(0).BgYellow()&YellowBg != 0, "not a yellow background")
+ assert.True(t, Color(BlackBg).BgYellow()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBlue(t *testing.T) {
+ assert.True(t, Color(0).BgBlue()&BlueBg != 0, "not a blue background")
+ assert.True(t, Color(BlackBg).BgBlue()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgMagenta(t *testing.T) {
+ assert.True(t, Color(0).BgMagenta()&MagentaBg != 0,
+ "not a magenta background")
+ assert.True(t, Color(BlackBg).BgMagenta()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgCyan(t *testing.T) {
+ assert.True(t, Color(0).BgCyan()&CyanBg != 0, "not a cyan background")
+ assert.True(t, Color(BlackBg).BgCyan()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgWhite(t *testing.T) {
+ assert.True(t, Color(0).BgWhite()&WhiteBg != 0, "not a white background")
+ assert.True(t, Color(BlackBg).BgWhite()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightBlack(t *testing.T) {
+ assert.True(t, Color(0).BgBrightBlack()&(BrightBg|BlackBg) != 0,
+ "not a bright black background")
+ assert.True(t, Color(RedBg).BgBrightBlack()&RedBg == flagBg,
+ "contains red background")
+}
+
+func TestColor_BgBrightRed(t *testing.T) {
+ assert.True(t, Color(0).BgBrightRed()&(BrightBg|RedBg) != 0,
+ "not a bright red background")
+ assert.True(t, Color(BlackBg).BgBrightRed()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightGreen(t *testing.T) {
+ assert.True(t, Color(0).BgBrightGreen()&(BrightBg|GreenBg) != 0,
+ "not a bright green background")
+ assert.True(t, Color(BlackBg).BgBrightGreen()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightYellow(t *testing.T) {
+ assert.True(t, Color(0).BgBrightYellow()&(BrightBg|YellowBg) != 0,
+ "not a bright yellow background")
+ assert.True(t, Color(BlackBg).BgBrightYellow()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightBlue(t *testing.T) {
+ assert.True(t, Color(0).BgBrightBlue()&(BrightBg|BlueBg) != 0,
+ "not a bright blue background")
+ assert.True(t, Color(BlackBg).BgBrightBlue()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightMagenta(t *testing.T) {
+ assert.True(t, Color(0).BgBrightMagenta()&(BrightBg|MagentaBg) != 0,
+ "not a bright magenta background")
+ assert.True(t, Color(BlackBg).BgBrightMagenta()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightCyan(t *testing.T) {
+ assert.True(t, Color(0).BgBrightCyan()&(BrightBg|CyanBg) != 0,
+ "not a bright cyan background")
+ assert.True(t, Color(BlackBg).BgBrightCyan()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgBrightWhite(t *testing.T) {
+ assert.True(t, Color(0).BgBrightWhite()&(BrightBg|WhiteBg) != 0,
+ "not a bright white background")
+ assert.True(t, Color(BlackBg).BgBrightWhite()&BlackBg == flagBg,
+ "contains black background")
+}
+
+func TestColor_BgIndex(t *testing.T) {
+ for i := 0; i < 256; i++ {
+ var ci = ColorIndex(i)
+ assert.True(t, Color(0).BgIndex(ci)&(flagBg) != 0,
+ "missing indexed background color")
+ assert.True(t, Color(BlackBg).BgIndex(ci)&BlackBg == flagBg,
+ "contains black background")
+ }
+}
+
+func TestColor_BgGray(t *testing.T) {
+ for i := GrayIndex(0); i <= 25; i++ {
+ assert.Truef(t, Color(0).BgGray(i)&(flagBg) != 0,
+ "missing indexed gray background color, gray index %d", i)
+ assert.Truef(t, Color(BlackBg).BgGray(i)&BlackBg == flagBg,
+ "contains black background, gray index %d", i)
}
}
diff --git a/config.go b/config.go
new file mode 100644
index 0000000..f659de5
--- /dev/null
+++ b/config.go
@@ -0,0 +1,120 @@
+//
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
+// This program is free software. It comes without any warranty,
+// to the extent permitted by applicable law. You can redistribute
+// it and/or modify it under the terms of the Unlicense. See LICENSE
+// file for more details or see below.
+//
+
+//
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// For more information, please refer to <http://unlicense.org/>
+//
+
+package aurora
+
+import "flag"
+
+// Config represents configurations of a colorizer.
+type Config struct {
+ // Colors feature. Enable colors if true.
+ Colors bool `json:"colors" yaml:"colors" toml:"colors" mapstructure:"colors"`
+ // Hyperlinks feature. Enable hyperlinks if true.
+ Hyperlinks bool `json:"hyperlinks" yaml:"hyperlinks" toml:"hyperlinks" mapstructure:"hyperlinks"`
+}
+
+// NewConfig returns new default Config.
+func NewConfig() (conf Config) {
+ conf.Colors = true
+ conf.Hyperlinks = true
+ return
+}
+
+// AddFlags to given *flag.FlagSet. The prefix used as prefix for flags.
+// It may be used to parse commandline flags. For example
+//
+// var conf Config
+// conf.AddFlags(flag.CommandLine, "colors.")
+// flag.Parse()
+//
+// for a main package, and use with flags commandline flags,
+//
+// go run main.go -colors.colors -colors.hyperlinks
+//
+// to enable or disable features. A colorizer can be created, for example,
+//
+// var colorizer = New(conf.Options()...)
+func (c *Config) AddFlags(fset *flag.FlagSet, prefix string) {
+ fset.BoolVar(&c.Colors,
+ prefix+"colors",
+ c.Colors,
+ "enable colors")
+ fset.BoolVar(&c.Hyperlinks,
+ prefix+"hyperlinks",
+ c.Hyperlinks,
+ "enable hyperlinks")
+}
+
+// Apply given options for the Config.
+func (c *Config) Apply(opts ...Option) {
+ for _, opt := range opts {
+ opt(c)
+ }
+}
+
+// Options by the Config.
+func (c *Config) Options() (opts []Option) {
+ return []Option{
+ WithColors(c.Colors),
+ WithHyperlinks(c.Hyperlinks),
+ }
+}
+
+func (c *Config) colorConfig() (cc colorConfig) {
+ if c.Colors {
+ cc |= colorPin
+ }
+ if c.Hyperlinks {
+ cc |= hyperlinksPin
+ }
+ return
+}
+
+// An Option function.
+type Option func(*Config)
+
+// WithColors is an Option that used to enable or disable colors.
+func WithColors(t bool) Option {
+ return func(c *Config) {
+ c.Colors = t
+ }
+}
+
+// WithHyperlinks is an Option that used to enable or disable links.
+func WithHyperlinks(t bool) Option {
+ return func(c *Config) {
+ c.Hyperlinks = t
+ }
+}
diff --git a/config_test.go b/config_test.go
new file mode 100644
index 0000000..5eae665
--- /dev/null
+++ b/config_test.go
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
+// This program is free software. It comes without any warranty,
+// to the extent permitted by applicable law. You can redistribute
+// it and/or modify it under the terms of the Unlicense. See LICENSE
+// file for more details or see below.
+//
+
+//
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// For more information, please refer to <http://unlicense.org/>
+//
+
+package aurora
+
+import (
+ "flag"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestNewConfig(t *testing.T) {
+ assert.Equal(t, Config{
+ Colors: true,
+ Hyperlinks: true,
+ }, NewConfig())
+}
+
+func TestConfig_AddFlags(t *testing.T) {
+ // set to true
+ var fset = flag.NewFlagSet("x", flag.ContinueOnError)
+ var conf = NewConfig()
+ conf.AddFlags(fset, "testing.")
+ var err = fset.Parse([]string{
+ "-testing.colors",
+ "-testing.hyperlinks",
+ })
+ require.NoError(t, err)
+ assert.True(t, conf.Colors)
+ assert.True(t, conf.Hyperlinks)
+ // set to true & false
+ fset = flag.NewFlagSet("x", flag.ContinueOnError)
+ conf.AddFlags(fset, "testing.")
+ err = fset.Parse([]string{
+ "-testing.colors=t",
+ "-testing.hyperlinks=f",
+ })
+ require.NoError(t, err)
+ assert.True(t, conf.Colors)
+ assert.False(t, conf.Hyperlinks)
+ // set to false & true
+ fset = flag.NewFlagSet("x", flag.ContinueOnError)
+ conf.AddFlags(fset, "testing.")
+ err = fset.Parse([]string{
+ "-testing.colors=f",
+ "-testing.hyperlinks=t",
+ })
+ require.NoError(t, err)
+ assert.False(t, conf.Colors)
+ assert.True(t, conf.Hyperlinks)
+ // set to false
+ fset = flag.NewFlagSet("x", flag.ContinueOnError)
+ conf.AddFlags(fset, "testing.")
+ err = fset.Parse([]string{
+ "-testing.colors=f",
+ "-testing.hyperlinks=f",
+ })
+ require.NoError(t, err)
+ assert.False(t, conf.Colors)
+ assert.False(t, conf.Hyperlinks)
+}
+
+func TestConfig_Apply(t *testing.T) {
+ var conf = NewConfig()
+ conf.Apply(WithColors(false), WithHyperlinks(false))
+ assert.Equal(t, Config{
+ Colors: false,
+ Hyperlinks: false,
+ }, conf)
+}
+
+func TestConfig_Options(t *testing.T) {
+ var (
+ c1 = NewConfig()
+ c2 Config
+ )
+ c2.Apply(c1.Options()...)
+ assert.Equal(t, Config{
+ Colors: true,
+ Hyperlinks: true,
+ }, c2)
+}
+
+func TestConfig_colorConfig(t *testing.T) {
+ var conf = NewConfig()
+ assert.Equal(t, colorPin|hyperlinksPin, conf.colorConfig())
+ conf.Colors = false
+ assert.Equal(t, hyperlinksPin, conf.colorConfig())
+ conf.Hyperlinks = false
+ assert.Equal(t, colorConfig(0), conf.colorConfig())
+}
+
+func TestWithColors(t *testing.T) {
+ var conf Config
+ // turn to true
+ conf.Apply(WithColors(true))
+ assert.Equal(t, Config{
+ Colors: true,
+ Hyperlinks: false,
+ }, conf)
+ // turn to false
+ conf.Apply(WithColors(false))
+ assert.Equal(t, Config{
+ Colors: false,
+ Hyperlinks: false,
+ }, conf)
+}
+
+func TestWithHyperlinks(t *testing.T) {
+ var conf Config
+ // turn to true
+ conf.Apply(WithHyperlinks(true))
+ assert.Equal(t, Config{
+ Colors: false,
+ Hyperlinks: true,
+ }, conf)
+ // turn to false
+ conf.Apply(WithHyperlinks(false))
+ assert.Equal(t, Config{
+ Colors: false,
+ Hyperlinks: false,
+ }, conf)
+}
diff --git a/debian/changelog b/debian/changelog
index 69218ad..8ef2c3a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+golang-github-logrusorgru-aurora (4.0.0-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Wed, 14 Dec 2022 18:15:44 -0000
+
golang-github-logrusorgru-aurora (3.0.0-2) unstable; urgency=medium
[ Nilesh Patra ]
diff --git a/example_test.go b/example_test.go
index 9ad16f2..317f47d 100644
--- a/example_test.go
+++ b/example_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2019 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -7,19 +7,30 @@
//
//
-// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-// Version 2, December 2004
+// This is free and unencumbered software released into the public domain.
//
-// Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
//
-// Everyone is permitted to copy and distribute verbatim or modified
-// copies of this license document, and changing it is allowed as long
-// as the name is changed.
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
//
-// DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
-// TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
//
-// 0. You just DO WHAT THE FUCK YOU WANT TO.
+// For more information, please refer to <http://unlicense.org/>
//
package aurora
@@ -40,15 +51,15 @@ func ExampleBold() {
// Output: value: [1;32m99[0m
}
-func ExampleNewAurora_no_colors() {
- a := NewAurora(false)
+func ExampleNew_no_colors() {
+ var a = New(WithColors(false), WithHyperlinks(false))
fmt.Println(a.Red("Not red"))
// Output: Not red
}
-func ExampleNewAurora_colors() {
- a := NewAurora(true)
+func ExampleNew_colors() {
+ var a = New()
fmt.Println(a.Red("Red"))
// Output: [31mRed[0m
@@ -71,3 +82,9 @@ func ExampleSprintf() {
// Output: [34mwe've got [0;36m5[0;34m cats, but want [0;1;35m25[0;34m[0m
}
+
+func ExampleHyperlink() {
+ fmt.Println(Hyperlink(Red("Example"), "http://example.com/"))
+
+ // Output: ]8;;http://example.com/\[31mExample[0m]8;;\
+}
diff --git a/go.mod b/go.mod
index bc595b2..c1e237c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,11 @@
-module github.com/logrusorgru/aurora/v3
+module github.com/logrusorgru/aurora/v4
-go 1.14
+go 1.19
+
+require github.com/stretchr/testify v1.8.0
+
+require (
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..5164829
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,15 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/hyperlinks.go b/hyperlinks.go
new file mode 100644
index 0000000..929159c
--- /dev/null
+++ b/hyperlinks.go
@@ -0,0 +1,283 @@
+//
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
+// This program is free software. It comes without any warranty,
+// to the extent permitted by applicable law. You can redistribute
+// it and/or modify it under the terms of the Unlicense. See LICENSE
+// file for more details or see below.
+//
+
+//
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// For more information, please refer to <http://unlicense.org/>
+//
+
+package aurora
+
+import (
+ "fmt"
+ "io"
+)
+
+const (
+ linkStartEsc = "\033]8;"
+ linkMiddleEsc = "\033\\"
+ linkEndEsc = linkStartEsc + ";" + linkMiddleEsc
+)
+
+// Hyperlinks related constants
+const (
+ HyperlinkIDKey = "id" // hyperlink id parameter key
+)
+
+// The HyperlinkParam represents a hyperlink parameter.
+type HyperlinkParam struct {
+ Key string // parameter name
+ Value string // parameter value
+}
+
+func (hp HyperlinkParam) stringLen() int {
+ return len(hp.Key) + 1 + len(hp.Value)
+}
+
+// String represents the HyperlinkParam as string, e.g. in key=value form.
+func (hp HyperlinkParam) String() string {
+ return hp.Key + "=" + hp.Value
+}
+
+// IsValidHyperlinkTarget returns true if the target contains symbols only
+// in 32-126 ASCII range. All symbols outside this range should be URL-escaped.
+func IsValidHyperlinkTarget(target string) (valid bool) {
+ // we can walk over bytes, without Unicode runes decoding
+ for i := 0; i < len(target); i++ {
+ if target[i] < 32 || 126 < target[i] {
+ return // false, should be URL-escaped
+ }
+ }
+ return true
+}
+
+// range over bytes (not Unicode runes) and check
+func containsAny(in string, any ...byte) (contains bool) {
+ for i := 0; i < len(in); i++ {
+ for _, b := range any {
+ if in[i] == b {
+ return true
+ }
+ }
+ }
+ return // false
+}
+
+// IsValidHyperlinkParam returns true for given string, if the string
+// is valid hyperlink target (see IsValidHyperlinkTarget) and doesn't
+// contains ':', ';' and '='.
+func IsValidHyperlinkParam(param string) (valid bool) {
+ return IsValidHyperlinkTarget(param) && !containsAny(param, ':', ';', '=')
+}
+
+// HyperlinkID returns list of HyperlinkParams that contains only id parameter
+// with given value of the id parameter.
+func HyperlinkID(id string) HyperlinkParam {
+ return HyperlinkParam{
+ Key: HyperlinkIDKey,
+ Value: id,
+ }
+}
+
+type hyperlink struct {
+ target string // hyperlink target
+ params []HyperlinkParam // hyperlink parameters
+}
+
+func (h *hyperlink) isExists() (ok bool) {
+ if h == nil {
+ return // does not exist
+ }
+ return h.target != ""
+}
+
+func (h *hyperlink) stringParamsLen() (ln int) {
+ for i, p := range h.params {
+ if i > 0 {
+ ln++ // + colon separator
+ }
+ ln += p.stringLen()
+ }
+ return
+}
+
+func (h *hyperlink) headLen() int {
+ return len(linkStartEsc) +
+ h.stringParamsLen() +
+ len(";") +
+ len(h.target) +
+ +len(linkMiddleEsc)
+}
+
+func (h *hyperlink) headBytes() (t []byte) {
+ t = make([]byte, 0, h.headLen())
+
+ t = append(t, linkStartEsc...)
+ for i, param := range h.params {
+ if i > 0 {
+ t = append(t, ':')
+ }
+ t = append(t, param.Key...)
+ t = append(t, '=')
+ t = append(t, param.Value...)
+ }
+ t = append(t, ';')
+ t = append(t, h.target...)
+ t = append(t, linkMiddleEsc...)
+ return
+}
+
+func (h *hyperlink) tailLen() int {
+ return len(linkEndEsc)
+}
+
+func (h *hyperlink) tailBytes() []byte {
+ return []byte(linkEndEsc)
+}
+
+func (h *hyperlink) writeHead(w io.Writer) {
+ if h == nil || h.target == "" {
+ return
+ }
+ w.Write(h.headBytes()) //nolint
+}
+
+func (h *hyperlink) writeTail(w io.Writer) {
+ if h == nil || h.target == "" {
+ return
+ }
+ w.Write(h.tailBytes()) //nolint
+}
+
+func shouldEscape(c byte) bool {
+ return c < 32 || 126 < c
+}
+
+func isHex(c byte) bool {
+ switch {
+ case '0' <= c && c <= '9':
+ return true
+ case 'a' <= c && c <= 'f':
+ return true
+ case 'A' <= c && c <= 'F':
+ return true
+ }
+ return false
+}
+
+func unhex(c byte) byte {
+ switch {
+ case '0' <= c && c <= '9':
+ return c - '0'
+ case 'a' <= c && c <= 'f':
+ return c - 'a' + 10
+ case 'A' <= c && c <= 'F':
+ return c - 'A' + 10
+ }
+ return 0
+}
+
+// HyperlinkEscape escapes all symbols of given string out of [32; 126] range
+// using URL-encoding. Used to escape a hyperlink target.
+func HyperlinkEscape(s string) string {
+
+ var hexCount int
+ for i := 0; i < len(s); i++ {
+ if shouldEscape(s[i]) {
+ hexCount++
+ }
+ }
+
+ if hexCount == 0 {
+ return s
+ }
+
+ const upperhex = "0123456789ABCDEF"
+
+ var (
+ t = make([]byte, len(s)+2*hexCount)
+ j int
+ )
+
+ for i := 0; i < len(s); i++ {
+ switch c := s[i]; {
+ case shouldEscape(c):
+ t[j] = '%'
+ t[j+1] = upperhex[c>>4]
+ t[j+2] = upperhex[c&15]
+ j += 3
+ default:
+ t[j] = s[i]
+ j++
+ }
+ }
+
+ return string(t)
+}
+
+// HyperlinkUnescape reverts a string escaped by the HyperlinkEscape.
+func HyperlinkUnescape(s string) (raw string, err error) {
+
+ var n int
+ for i := 0; i < len(s); {
+ switch s[i] {
+ case '%':
+ n++
+ if i+2 >= len(s) || !isHex(s[i+1]) || !isHex(s[i+2]) {
+ s = s[i:]
+ if len(s) > 3 {
+ s = s[:3]
+ }
+ return "", fmt.Errorf("invalid URL-escape sequence: %q", s)
+ }
+ i += 3
+ default:
+ i++
+ }
+ }
+
+ if n == 0 {
+ return s, nil
+ }
+
+ var t = make([]byte, 0, len(s)-2*n)
+
+ for i := 0; i < len(s); i++ {
+ switch s[i] {
+ case '%':
+ t = append(t, unhex(s[i+1])<<4|unhex(s[i+2]))
+ i += 2
+ default:
+ t = append(t, s[i])
+ }
+ }
+
+ return string(t), nil
+}
diff --git a/hyperlinks_test.go b/hyperlinks_test.go
new file mode 100644
index 0000000..74f2225
--- /dev/null
+++ b/hyperlinks_test.go
@@ -0,0 +1,119 @@
+//
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
+// This program is free software. It comes without any warranty,
+// to the extent permitted by applicable law. You can redistribute
+// it and/or modify it under the terms of the Unlicense. See LICENSE
+// file for more details or see below.
+//
+
+//
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// For more information, please refer to <http://unlicense.org/>
+//
+
+package aurora
+
+import (
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+func TestHyperlinkParam_stringLen(t *testing.T) {
+ var param HyperlinkParam
+ assert.Equal(t, 1, param.stringLen())
+ param.Key, param.Value = "some", "thing"
+ assert.Equal(t, 1+len("some")+len("thing"), param.stringLen())
+}
+
+func TestHyperlinkParam_String(t *testing.T) {
+ var param HyperlinkParam
+ assert.Equal(t, "=", param.String())
+ param.Key, param.Value = "some", "thing"
+ assert.Equal(t, "some=thing", param.String())
+}
+
+func TestIsValidHyperlinkTarget(t *testing.T) {
+ assert.True(t, IsValidHyperlinkTarget("http://example.com/path?query=true"))
+ assert.True(t, IsValidHyperlinkTarget("mailto:user@example.com"))
+ assert.False(t, IsValidHyperlinkTarget("http://пример.тест/путь?запрос=да"))
+ assert.False(t, IsValidHyperlinkTarget("mailto:пользователь@пример.тест"))
+}
+
+func TestIsValidHyperlinkParam(t *testing.T) {
+ assert.True(t, IsValidHyperlinkParam("id"))
+ assert.True(t, IsValidHyperlinkParam("a_param-key"))
+ assert.False(t, IsValidHyperlinkParam("value:true"))
+ assert.False(t, IsValidHyperlinkParam("value=true"))
+ assert.False(t, IsValidHyperlinkParam("v1;v2"))
+}
+
+func TestHyperlinkID(t *testing.T) {
+ assert.Equal(t, HyperlinkParam{
+ Key: HyperlinkIDKey,
+ Value: "value",
+ }, HyperlinkID("value"))
+}
+
+func Test_unhex(t *testing.T) {
+ assert.Zero(t, unhex(0))
+}
+
+func TestHyperlinkEscape(t *testing.T) {
+ var val = "http://example.com/path?query=true"
+ assert.Equal(t, val, HyperlinkEscape(val))
+ val = "mailto:user@example.com"
+ assert.Equal(t, val, HyperlinkEscape(val))
+ val = "http://пример.тест/путь?запрос=да"
+ assert.True(t, IsValidHyperlinkTarget(HyperlinkEscape(val)))
+ val = "mailto:пользователь@пример.тест"
+ assert.True(t, IsValidHyperlinkTarget(HyperlinkEscape(val)))
+}
+
+func TestHyperlinkUnescape(t *testing.T) {
+ for _, val := range []string{
+ "http://example.com/path?query=true",
+ "mailto:user@example.com",
+ "http://пример.тест/путь?запрос=да",
+ "mailto:пользователь@пример.тест",
+ } {
+ var got, err = HyperlinkUnescape(HyperlinkEscape(val))
+ require.NoError(t, err)
+ assert.Equal(t, val, got)
+ }
+ var _, err = HyperlinkUnescape("%%%%")
+ assert.Error(t, err)
+ var (
+ val = "значение"
+ escaped = HyperlinkEscape(val)
+ back string
+ )
+ escaped = strings.ToLower(escaped)
+ back, err = HyperlinkUnescape(escaped)
+ assert.NoError(t, err)
+ assert.Equal(t, val, back)
+}
diff --git a/sprintf.go b/sprintf.go
index b92d593..b1389a6 100644
--- a/sprintf.go
+++ b/sprintf.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -37,27 +37,89 @@ package aurora
import (
"fmt"
+ "strconv"
+ "unicode/utf8"
)
-// Sprintf allows to use Value as format. For example
-//
-// v := Sprintf(Red("total: +3.5f points"), Blue(3.14))
-//
-// In this case "total:" and "points" will be red, but
-// 3.14 will be blue. But, in another example
-//
-// v := Sprintf(Red("total: +3.5f points"), 3.14)
-//
-// full string will be red. And no way to clear 3.14 to
-// default format and color
-func Sprintf(format interface{}, args ...interface{}) string {
+type tailedValue struct {
+ Value
+ tail Color
+}
+
+func (v *tailedValue) Format(s fmt.State, verb rune) {
+
+ // it's enough for many cases (%-+020.10f)
+ // % - 1
+ // availFlags - 3 (5)
+ // width - 2
+ // prec - 3 (.23)
+ // verb - 1
+ // --------------
+ // 10
+ // +
+ // \033[ 5
+ // 0;1;3;4;5;7;8;9;20;21;51;52;53 30
+ // 38;5;216 8
+ // 48;5;216 8
+ // m 1
+ // +
+ // \033[0m 7
+ //
+ // x2 (possible tail color)
+ //
+ // 10 + 59 * 2 = 128
+
+ var (
+ format = make([]byte, 0, 128)
+ color = v.Color()
+ )
+ if color != 0 {
+ format = append(format, esc...)
+ format = color.appendNos(format, v.tail != 0)
+ format = append(format, 'm')
+ }
+ format = append(format, '%')
+ var f byte
+ for i := 0; i < len(availFlags); i++ {
+ if f = availFlags[i]; s.Flag(int(f)) {
+ format = append(format, f)
+ }
+ }
+ var width, prec int
+ var ok bool
+ if width, ok = s.Width(); ok {
+ format = strconv.AppendInt(format, int64(width), 10)
+ }
+ if prec, ok = s.Precision(); ok {
+ format = append(format, '.')
+ format = strconv.AppendInt(format, int64(prec), 10)
+ }
+ if verb > utf8.RuneSelf {
+ format = append(format, string(verb)...)
+ } else {
+ format = append(format, byte(verb))
+ }
+ if color != 0 {
+ if v.tail != 0 {
+ // set next (previous) format clearing current one
+ format = append(format, esc...)
+ format = v.tail.appendNos(format, true)
+ format = append(format, 'm')
+ } else {
+ format = append(format, clear...) // just clear
+ }
+ }
+ fmt.Fprintf(s, string(format), v.Value.Value())
+}
+
+func sprintf(format interface{}, args ...interface{}) string {
switch ft := format.(type) {
case string:
return fmt.Sprintf(ft, args...)
case Value:
for i, v := range args {
if val, ok := v.(Value); ok {
- args[i] = val.setTail(ft.Color())
+ args[i] = &tailedValue{Value: val, tail: ft.Color()}
continue
}
}
diff --git a/sprintf_test.go b/sprintf_test.go
index ee9a08f..370662f 100644
--- a/sprintf_test.go
+++ b/sprintf_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -37,19 +37,52 @@ package aurora
import (
"testing"
+
+ "github.com/stretchr/testify/assert"
)
type noString string
func Test_Sprintf(t *testing.T) {
- //b := Black("x")
- v := Sprintf(noString("delta: +%d"), 3)
- if v != "delta: +3" {
- t.Error("Sprintf: wrong result")
- }
- v = Sprintf(Red("deltas: +%d, %d, %d points"), 3, 5, 9)
- want := "\033[31mdeltas: +3, 5, 9 points\033[0m"
- if v != want {
- t.Errorf("Sprintf: want: %q, got %q", want, v)
- }
+ var want, got string
+
+ want = "delta: +3"
+ got = Sprintf(noString("delta: +%d"), 3)
+ assert.Equal(t, want, got)
+
+ want = "\033[31mdeltas: +3, 5, 9 points\033[0m"
+ got = Sprintf(Red("deltas: +%d, %d, %d points"), 3, 5, 9)
+ assert.Equal(t, want, got)
+
+ // %s
+ want = `[31mquoted: [0;34m "blue"[0;31m` +
+ `, [0;32m green[0;31m[0m`
+ got = Sprintf(Red("quoted: % 10q, % 10s"), Blue("blue"), Green("green"))
+ assert.Equal(t, want, got)
+
+ // on string
+ want = `quoted: [34mblue[0m, [32mgreen[0m`
+ got = Sprintf("quoted: %s, %s", Blue("blue"), Green("green"))
+ assert.Equal(t, want, got)
+
+ // no tail
+ want = `quoted: [34mblue[0m, [32mgreen[0m`
+ got = Sprintf(Clear("quoted: %s, %s"), Blue("blue"), Green("green"))
+ assert.Equal(t, want, got)
+
+ // precision
+ want = `[31mvalue: [0;34m2.78[0;31m[0m`
+ got = Sprintf(Red("value: %1.2f"), Blue(2.7834))
+ assert.Equal(t, want, got)
+
+ // wide verb
+ want = `[31m[0;34m%!世(float64=+2.78)[0;31m[0m`
+ got = Sprintf(Red("%+1.3世"), Blue(2.7834))
+ assert.Equal(t, want, got)
+
+ // decolor
+ var au = New(WithColors(false), WithHyperlinks(false))
+ want = `+2.783`
+ got = au.Sprintf(Red("%+1.3f"), Blue(2.7834))
+ assert.Equal(t, want, got)
}
diff --git a/value.go b/value.go
index feda25a..9b5f4f0 100644
--- a/value.go
+++ b/value.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -41,362 +41,14 @@ import (
"unicode/utf8"
)
-// A Value represents any printable value
-// with it's color
-type Value interface {
- // String returns string with colors. If there are any color
- // or format the string will be terminated with \033[0m
- fmt.Stringer
- // Format implements fmt.Formatter interface
- fmt.Formatter
- // Color returns value's color
- Color() Color
- // Value returns value's value (welcome to the tautology club)
- Value() interface{}
-
- // internals
- tail() Color
- setTail(Color) Value
-
- // Bleach returns copy of original value without colors
- //
- // Deprecated: use Reset instead.
- Bleach() Value
- // Reset colors and formats
- Reset() Value
-
- //
- // Formats
- //
- //
- // Bold or increased intensity (1).
- Bold() Value
- // Faint, decreased intensity, reset the Bold (2).
- Faint() Value
- //
- // DoublyUnderline or Bold off, double-underline
- // per ECMA-48 (21). It depends.
- DoublyUnderline() Value
- // Fraktur, rarely supported (20).
- Fraktur() Value
- //
- // Italic, not widely supported, sometimes
- // treated as inverse (3).
- Italic() Value
- // Underline (4).
- Underline() Value
- //
- // SlowBlink, blinking less than 150
- // per minute (5).
- SlowBlink() Value
- // RapidBlink, blinking 150+ per minute,
- // not widely supported (6).
- RapidBlink() Value
- // Blink is alias for the SlowBlink.
- Blink() Value
- //
- // Reverse video, swap foreground and
- // background colors (7).
- Reverse() Value
- // Inverse is alias for the Reverse
- Inverse() Value
- //
- // Conceal, hidden, not widely supported (8).
- Conceal() Value
- // Hidden is alias for the Conceal
- Hidden() Value
- //
- // CrossedOut, characters legible, but
- // marked for deletion (9).
- CrossedOut() Value
- // StrikeThrough is alias for the CrossedOut.
- StrikeThrough() Value
- //
- // Framed (51).
- Framed() Value
- // Encircled (52).
- Encircled() Value
- //
- // Overlined (53).
- Overlined() Value
-
- //
- // Foreground colors
- //
- //
- // Black foreground color (30)
- Black() Value
- // Red foreground color (31)
- Red() Value
- // Green foreground color (32)
- Green() Value
- // Yellow foreground color (33)
- Yellow() Value
- // Brown foreground color (33)
- //
- // Deprecated: use Yellow instead, following specification
- Brown() Value
- // Blue foreground color (34)
- Blue() Value
- // Magenta foreground color (35)
- Magenta() Value
- // Cyan foreground color (36)
- Cyan() Value
- // White foreground color (37)
- White() Value
- //
- // Bright foreground colors
- //
- // BrightBlack foreground color (90)
- BrightBlack() Value
- // BrightRed foreground color (91)
- BrightRed() Value
- // BrightGreen foreground color (92)
- BrightGreen() Value
- // BrightYellow foreground color (93)
- BrightYellow() Value
- // BrightBlue foreground color (94)
- BrightBlue() Value
- // BrightMagenta foreground color (95)
- BrightMagenta() Value
- // BrightCyan foreground color (96)
- BrightCyan() Value
- // BrightWhite foreground color (97)
- BrightWhite() Value
- //
- // Other
- //
- // Index of pre-defined 8-bit foreground color
- // from 0 to 255 (38;5;n).
- //
- // 0- 7: standard colors (as in ESC [ 30–37 m)
- // 8- 15: high intensity colors (as in ESC [ 90–97 m)
- // 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
- // 232-255: grayscale from black to white in 24 steps
- //
- Index(n uint8) Value
- // Gray from 0 to 24.
- Gray(n uint8) Value
-
- //
- // Background colors
- //
- //
- // BgBlack background color (40)
- BgBlack() Value
- // BgRed background color (41)
- BgRed() Value
- // BgGreen background color (42)
- BgGreen() Value
- // BgYellow background color (43)
- BgYellow() Value
- // BgBrown background color (43)
- //
- // Deprecated: use BgYellow instead, following specification
- BgBrown() Value
- // BgBlue background color (44)
- BgBlue() Value
- // BgMagenta background color (45)
- BgMagenta() Value
- // BgCyan background color (46)
- BgCyan() Value
- // BgWhite background color (47)
- BgWhite() Value
- //
- // Bright background colors
- //
- // BgBrightBlack background color (100)
- BgBrightBlack() Value
- // BgBrightRed background color (101)
- BgBrightRed() Value
- // BgBrightGreen background color (102)
- BgBrightGreen() Value
- // BgBrightYellow background color (103)
- BgBrightYellow() Value
- // BgBrightBlue background color (104)
- BgBrightBlue() Value
- // BgBrightMagenta background color (105)
- BgBrightMagenta() Value
- // BgBrightCyan background color (106)
- BgBrightCyan() Value
- // BgBrightWhite background color (107)
- BgBrightWhite() Value
- //
- // Other
- //
- // BgIndex of 8-bit pre-defined background color
- // from 0 to 255 (48;5;n).
- //
- // 0- 7: standard colors (as in ESC [ 40–47 m)
- // 8- 15: high intensity colors (as in ESC [100–107 m)
- // 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
- // 232-255: grayscale from black to white in 24 steps
- //
- BgIndex(n uint8) Value
- // BgGray from 0 to 24.
- BgGray(n uint8) Value
-
- //
- // Special
- //
- // Colorize removes existing colors and
- // formats of the argument and applies given.
- Colorize(color Color) Value
-}
-
-// Value without colors
-
-type valueClear struct {
- value interface{}
-}
-
-func (vc valueClear) String() string { return fmt.Sprint(vc.value) }
-
-func (vc valueClear) Color() Color { return 0 }
-func (vc valueClear) Value() interface{} { return vc.value }
-
-func (vc valueClear) tail() Color { return 0 }
-func (vc valueClear) setTail(Color) Value { return vc }
-
-func (vc valueClear) Bleach() Value { return vc }
-func (vc valueClear) Reset() Value { return vc }
-
-func (vc valueClear) Bold() Value { return vc }
-func (vc valueClear) Faint() Value { return vc }
-func (vc valueClear) DoublyUnderline() Value { return vc }
-func (vc valueClear) Fraktur() Value { return vc }
-func (vc valueClear) Italic() Value { return vc }
-func (vc valueClear) Underline() Value { return vc }
-func (vc valueClear) SlowBlink() Value { return vc }
-func (vc valueClear) RapidBlink() Value { return vc }
-func (vc valueClear) Blink() Value { return vc }
-func (vc valueClear) Reverse() Value { return vc }
-func (vc valueClear) Inverse() Value { return vc }
-func (vc valueClear) Conceal() Value { return vc }
-func (vc valueClear) Hidden() Value { return vc }
-func (vc valueClear) CrossedOut() Value { return vc }
-func (vc valueClear) StrikeThrough() Value { return vc }
-func (vc valueClear) Framed() Value { return vc }
-func (vc valueClear) Encircled() Value { return vc }
-func (vc valueClear) Overlined() Value { return vc }
-
-func (vc valueClear) Black() Value { return vc }
-func (vc valueClear) Red() Value { return vc }
-func (vc valueClear) Green() Value { return vc }
-func (vc valueClear) Yellow() Value { return vc }
-func (vc valueClear) Brown() Value { return vc }
-func (vc valueClear) Blue() Value { return vc }
-func (vc valueClear) Magenta() Value { return vc }
-func (vc valueClear) Cyan() Value { return vc }
-func (vc valueClear) White() Value { return vc }
-func (vc valueClear) BrightBlack() Value { return vc }
-func (vc valueClear) BrightRed() Value { return vc }
-func (vc valueClear) BrightGreen() Value { return vc }
-func (vc valueClear) BrightYellow() Value { return vc }
-func (vc valueClear) BrightBlue() Value { return vc }
-func (vc valueClear) BrightMagenta() Value { return vc }
-func (vc valueClear) BrightCyan() Value { return vc }
-func (vc valueClear) BrightWhite() Value { return vc }
-func (vc valueClear) Index(uint8) Value { return vc }
-func (vc valueClear) Gray(uint8) Value { return vc }
-
-func (vc valueClear) BgBlack() Value { return vc }
-func (vc valueClear) BgRed() Value { return vc }
-func (vc valueClear) BgGreen() Value { return vc }
-func (vc valueClear) BgYellow() Value { return vc }
-func (vc valueClear) BgBrown() Value { return vc }
-func (vc valueClear) BgBlue() Value { return vc }
-func (vc valueClear) BgMagenta() Value { return vc }
-func (vc valueClear) BgCyan() Value { return vc }
-func (vc valueClear) BgWhite() Value { return vc }
-func (vc valueClear) BgBrightBlack() Value { return vc }
-func (vc valueClear) BgBrightRed() Value { return vc }
-func (vc valueClear) BgBrightGreen() Value { return vc }
-func (vc valueClear) BgBrightYellow() Value { return vc }
-func (vc valueClear) BgBrightBlue() Value { return vc }
-func (vc valueClear) BgBrightMagenta() Value { return vc }
-func (vc valueClear) BgBrightCyan() Value { return vc }
-func (vc valueClear) BgBrightWhite() Value { return vc }
-func (vc valueClear) BgIndex(uint8) Value { return vc }
-func (vc valueClear) BgGray(uint8) Value { return vc }
-func (vc valueClear) Colorize(Color) Value { return vc }
-
-func (vc valueClear) Format(s fmt.State, verb rune) {
- // it's enough for many cases (%-+020.10f)
- // % - 1
- // availFlags - 3 (5)
- // width - 2
- // prec - 3 (.23)
- // verb - 1
- // --------------
- // 10
- format := make([]byte, 1, 10)
- format[0] = '%'
- var f byte
- for i := 0; i < len(availFlags); i++ {
- if f = availFlags[i]; s.Flag(int(f)) {
- format = append(format, f)
- }
- }
- var width, prec int
- var ok bool
- if width, ok = s.Width(); ok {
- format = strconv.AppendInt(format, int64(width), 10)
- }
- if prec, ok = s.Precision(); ok {
- format = append(format, '.')
- format = strconv.AppendInt(format, int64(prec), 10)
- }
- if verb > utf8.RuneSelf {
- format = append(format, string(verb)...)
- } else {
- format = append(format, byte(verb))
- }
- fmt.Fprintf(s, string(format), vc.value)
-}
-
-// Value within colors
-
-type value struct {
- value interface{} // value as it
- color Color // this color
- tailColor Color // tail color
-}
-
-func (v value) String() string {
- if v.color != 0 {
- if v.tailColor != 0 {
- return esc + v.color.Nos(true) + "m" +
- fmt.Sprint(v.value) +
- esc + v.tailColor.Nos(true) + "m"
- }
- return esc + v.color.Nos(false) + "m" + fmt.Sprint(v.value) + clear
- }
- return fmt.Sprint(v.value)
-}
-
-func (v value) Color() Color { return v.color }
-
-func (v value) Bleach() Value {
- v.color, v.tailColor = 0, 0
- return v
-}
-
-func (v value) Reset() Value {
- v.color, v.tailColor = 0, 0
- return v
-}
-
-func (v value) tail() Color { return v.tailColor }
-
-func (v value) setTail(t Color) Value {
- v.tailColor = t
- return v
-}
-
-func (v value) Value() interface{} { return v.value }
+// compile-time check
+var (
+ _ fmt.Stringer = Value{}
+ _ fmt.Formatter = Value{}
+ _ Colored = Value{}
+)
-func (v value) Format(s fmt.State, verb rune) {
+func coloredFormat(color Color, s fmt.State, verb rune) string {
// it's enough for many cases (%-+020.10f)
// % - 1
@@ -419,327 +71,567 @@ func (v value) Format(s fmt.State, verb rune) {
//
// 10 + 59 * 2 = 128
- format := make([]byte, 0, 128)
- if v.color != 0 {
+ var format = make([]byte, 0, 128)
+
+ if color != 0 {
format = append(format, esc...)
- format = v.color.appendNos(format, v.tailColor != 0)
+ format = color.appendNos(format, false)
format = append(format, 'm')
}
+
format = append(format, '%')
+
var f byte
for i := 0; i < len(availFlags); i++ {
if f = availFlags[i]; s.Flag(int(f)) {
format = append(format, f)
}
}
- var width, prec int
- var ok bool
+
+ var (
+ width, prec int
+ ok bool
+ )
if width, ok = s.Width(); ok {
format = strconv.AppendInt(format, int64(width), 10)
}
+
if prec, ok = s.Precision(); ok {
format = append(format, '.')
format = strconv.AppendInt(format, int64(prec), 10)
}
+
if verb > utf8.RuneSelf {
format = append(format, string(verb)...)
} else {
format = append(format, byte(verb))
}
- if v.color != 0 {
- if v.tailColor != 0 {
- // set next (previous) format clearing current one
- format = append(format, esc...)
- format = v.tailColor.appendNos(format, true)
- format = append(format, 'm')
+
+ if color != 0 {
+ format = append(format, clear...) // just clear
+ }
+
+ return string(format)
+}
+
+type colorConfig uint64
+
+const (
+ colorPin colorConfig = 1 << 32
+ hyperlinksPin colorConfig = 1 << 33
+)
+
+func (cc colorConfig) colorsEnabled() bool {
+ return cc&colorPin != 0
+}
+
+func (cc colorConfig) hyperlinksEnbaled() bool {
+ return cc&hyperlinksPin != 0
+}
+
+func (cc colorConfig) color() Color {
+ if cc.colorsEnabled() {
+ return Color(uint32(cc)) // lower 32 bits only
+ }
+ return 0 // even if a color set
+}
+
+func (cc colorConfig) resetColor() colorConfig {
+ return cc & (colorPin | hyperlinksPin)
+}
+
+// A Value represents any printable value
+// with or without colors, formats and a link.
+type Value struct {
+ value interface{} // value as is
+ cc colorConfig // color & config
+ hyperlink *hyperlink // hyperlink target and parameters
+}
+
+// String implements standard fmt.Stringer interface.
+func (v Value) String() string {
+ var (
+ t []byte
+ val = fmt.Sprint(v.value)
+ color = v.cc.color()
+ )
+
+ if v.cc.hyperlinksEnbaled() && v.hyperlink.isExists() {
+ var (
+ ln = len(val)
+ nos string
+ )
+ // calculate length
+ ln += v.hyperlink.headLen()
+ if color != 0 {
+ ln += len(esc)
+ nos = color.Nos(false)
+ ln += len(nos) + len("m")
+ ln += len(clear)
+ }
+ ln += v.hyperlink.tailLen()
+ // fill
+ t = make([]byte, 0, ln)
+ t = append(t, v.hyperlink.headBytes()...)
+ if color != 0 {
+ t = append(t, esc...)
+ t = append(t, nos...)
+ t = append(t, 'm')
+ t = append(t, val...)
+ t = append(t, clear...)
} else {
- format = append(format, clear...) // just clear
+ t = append(t, val...)
}
+ t = append(t, v.hyperlink.tailBytes()...)
+ return string(t)
+ }
+
+ // no links, only colors & formats
+ if color != 0 {
+ return esc + color.Nos(false) + "m" + val + clear
+ }
+
+ // no links, no colors, no formats, just the value
+ return val
+}
+
+// Color returns colors and formats of the Value.
+func (v Value) Color() Color {
+ return v.cc.color()
+}
+
+// Reset colors, formats and links.
+func (v Value) Reset() Value {
+ v.cc, v.hyperlink = v.cc.resetColor(), nil
+ return v
+}
+
+// Clear colors and formats, preserving links.
+func (v Value) Clear() Value {
+ v.cc = v.cc.resetColor()
+ return v
+}
+
+// Value returns value's value (welcome to the tautology club)
+func (v Value) Value() interface{} {
+ return v.value
+}
+
+// Format implements standard fmt.Formatter interface.
+func (v Value) Format(s fmt.State, verb rune) {
+ if !v.cc.hyperlinksEnbaled() {
+ fmt.Fprintf(s, coloredFormat(v.Color(), s, verb), v.value)
+ return
}
- fmt.Fprintf(s, string(format), v.value)
+ v.hyperlink.writeHead(s)
+ fmt.Fprintf(s, coloredFormat(v.Color(), s, verb), v.value)
+ v.hyperlink.writeTail(s)
}
-func (v value) Bold() Value {
- v.color = (v.color &^ FaintFm) | BoldFm
+// Formats
+//
+// Bold or increased intensity (1).
+func (v Value) Bold() Value {
+ v.cc = colorConfig(v.cc.color().Bold()) | v.cc.resetColor()
return v
}
-func (v value) Faint() Value {
- v.color = (v.color &^ BoldFm) | FaintFm
+// Faint, decreased intensity, reset the Bold (2).
+func (v Value) Faint() Value {
+ v.cc = colorConfig(v.cc.color().Faint()) | v.cc.resetColor()
return v
}
-func (v value) DoublyUnderline() Value {
- v.color |= DoublyUnderlineFm
+// DoublyUnderline or Bold off, double-underline per ECMA-48 (21). It depends.
+func (v Value) DoublyUnderline() Value {
+ v.cc = colorConfig(v.cc.color().DoublyUnderline()) | v.cc.resetColor()
return v
}
-func (v value) Fraktur() Value {
- v.color |= FrakturFm
+// Fraktur, rarely supported (20).
+func (v Value) Fraktur() Value {
+ v.cc = colorConfig(v.cc.color().Fraktur()) | v.cc.resetColor()
return v
}
-func (v value) Italic() Value {
- v.color |= ItalicFm
+// Italic, not widely supported, sometimes treated as inverse (3).
+func (v Value) Italic() Value {
+ v.cc = colorConfig(v.cc.color().Italic()) | v.cc.resetColor()
return v
}
-func (v value) Underline() Value {
- v.color |= UnderlineFm
+// Underline (4).
+func (v Value) Underline() Value {
+ v.cc = colorConfig(v.cc.color().Underline()) | v.cc.resetColor()
return v
}
-func (v value) SlowBlink() Value {
- v.color = (v.color &^ RapidBlinkFm) | SlowBlinkFm
+// SlowBlink, blinking less than 150 per minute (5).
+func (v Value) SlowBlink() Value {
+ v.cc = colorConfig(v.cc.color().SlowBlink()) | v.cc.resetColor()
return v
}
-func (v value) RapidBlink() Value {
- v.color = (v.color &^ SlowBlinkFm) | RapidBlinkFm
+// RapidBlink, blinking 150+ per minute, not widely supported (6).
+func (v Value) RapidBlink() Value {
+ v.cc = colorConfig(v.cc.color().RapidBlink()) | v.cc.resetColor()
return v
}
-func (v value) Blink() Value {
+// Blink is alias for the SlowBlink.
+func (v Value) Blink() Value {
return v.SlowBlink()
}
-func (v value) Reverse() Value {
- v.color |= ReverseFm
+// Reverse video, swap foreground and background colors (7).
+func (v Value) Reverse() Value {
+ v.cc = colorConfig(v.cc.color().Reverse()) | v.cc.resetColor()
return v
}
-func (v value) Inverse() Value {
+// Inverse is alias for the Reverse.
+func (v Value) Inverse() Value {
return v.Reverse()
}
-func (v value) Conceal() Value {
- v.color |= ConcealFm
+// Conceal, hidden, not widely supported (8).
+func (v Value) Conceal() Value {
+ v.cc = colorConfig(v.cc.color().Conceal()) | v.cc.resetColor()
return v
}
-func (v value) Hidden() Value {
+// Hidden is alias for the Conceal.
+func (v Value) Hidden() Value {
return v.Conceal()
}
-func (v value) CrossedOut() Value {
- v.color |= CrossedOutFm
+// CrossedOut, characters legible, but marked for deletion (9).
+func (v Value) CrossedOut() Value {
+ v.cc = colorConfig(v.cc.color().CrossedOut()) | v.cc.resetColor()
return v
}
-func (v value) StrikeThrough() Value {
+// StrikeThrough is alias for the CrossedOut.
+func (v Value) StrikeThrough() Value {
return v.CrossedOut()
}
-func (v value) Framed() Value {
- v.color |= FramedFm
+// Framed (51).
+func (v Value) Framed() Value {
+ v.cc = colorConfig(v.cc.color().Framed()) | v.cc.resetColor()
return v
}
-func (v value) Encircled() Value {
- v.color |= EncircledFm
+// Encircled (52).
+func (v Value) Encircled() Value {
+ v.cc = colorConfig(v.cc.color().Encircled()) | v.cc.resetColor()
return v
}
-func (v value) Overlined() Value {
- v.color |= OverlinedFm
+// Overlined (53).
+func (v Value) Overlined() Value {
+ v.cc = colorConfig(v.cc.color().Overlined()) | v.cc.resetColor()
return v
}
-func (v value) Black() Value {
- v.color = (v.color &^ maskFg) | BlackFg
+// Foreground colors.
+//
+// Black foreground color (30).
+func (v Value) Black() Value {
+ v.cc = colorConfig(v.cc.color().Black()) | v.cc.resetColor()
return v
}
-func (v value) Red() Value {
- v.color = (v.color &^ maskFg) | RedFg
+// Red foreground color (31).
+func (v Value) Red() Value {
+ v.cc = colorConfig(v.cc.color().Red()) | v.cc.resetColor()
return v
}
-func (v value) Green() Value {
- v.color = (v.color &^ maskFg) | GreenFg
+// Green foreground color (32).
+func (v Value) Green() Value {
+ v.cc = colorConfig(v.cc.color().Green()) | v.cc.resetColor()
return v
}
-func (v value) Yellow() Value {
- v.color = (v.color &^ maskFg) | YellowFg
+// Yellow foreground color (33).
+func (v Value) Yellow() Value {
+ v.cc = colorConfig(v.cc.color().Yellow()) | v.cc.resetColor()
return v
}
-func (v value) Brown() Value {
- return v.Yellow()
+// Blue foreground color (34).
+func (v Value) Blue() Value {
+ v.cc = colorConfig(v.cc.color().Blue()) | v.cc.resetColor()
+ return v
}
-func (v value) Blue() Value {
- v.color = (v.color &^ maskFg) | BlueFg
+// Magenta foreground color (35).
+func (v Value) Magenta() Value {
+ v.cc = colorConfig(v.cc.color().Magenta()) | v.cc.resetColor()
return v
}
-func (v value) Magenta() Value {
- v.color = (v.color &^ maskFg) | MagentaFg
+// Cyan foreground color (36).
+func (v Value) Cyan() Value {
+ v.cc = colorConfig(v.cc.color().Cyan()) | v.cc.resetColor()
return v
}
-func (v value) Cyan() Value {
- v.color = (v.color &^ maskFg) | CyanFg
+// White foreground color (37).
+func (v Value) White() Value {
+ v.cc = colorConfig(v.cc.color().White()) | v.cc.resetColor()
return v
}
-func (v value) White() Value {
- v.color = (v.color &^ maskFg) | WhiteFg
+// Bright foreground colors.
+//
+// BrightBlack foreground color (90).
+func (v Value) BrightBlack() Value {
+ v.cc = colorConfig(v.cc.color().BrightBlack()) | v.cc.resetColor()
return v
}
-func (v value) BrightBlack() Value {
- v.color = (v.color &^ maskFg) | BrightFg | BlackFg
+// BrightRed foreground color (91).
+func (v Value) BrightRed() Value {
+ v.cc = colorConfig(v.cc.color().BrightRed()) | v.cc.resetColor()
return v
}
-func (v value) BrightRed() Value {
- v.color = (v.color &^ maskFg) | BrightFg | RedFg
+// BrightGreen foreground color (92).
+func (v Value) BrightGreen() Value {
+ v.cc = colorConfig(v.cc.color().BrightGreen()) | v.cc.resetColor()
return v
}
-func (v value) BrightGreen() Value {
- v.color = (v.color &^ maskFg) | BrightFg | GreenFg
+// BrightYellow foreground color (93).
+func (v Value) BrightYellow() Value {
+ v.cc = colorConfig(v.cc.color().BrightYellow()) | v.cc.resetColor()
return v
}
-func (v value) BrightYellow() Value {
- v.color = (v.color &^ maskFg) | BrightFg | YellowFg
+// BrightBlue foreground color (94).
+func (v Value) BrightBlue() Value {
+ v.cc = colorConfig(v.cc.color().BrightBlue()) | v.cc.resetColor()
return v
}
-func (v value) BrightBlue() Value {
- v.color = (v.color &^ maskFg) | BrightFg | BlueFg
+// BrightMagenta foreground color (95).
+func (v Value) BrightMagenta() Value {
+ v.cc = colorConfig(v.cc.color().BrightMagenta()) | v.cc.resetColor()
return v
}
-func (v value) BrightMagenta() Value {
- v.color = (v.color &^ maskFg) | BrightFg | MagentaFg
+// BrightCyan foreground color (96).
+func (v Value) BrightCyan() Value {
+ v.cc = colorConfig(v.cc.color().BrightCyan()) | v.cc.resetColor()
return v
}
-func (v value) BrightCyan() Value {
- v.color = (v.color &^ maskFg) | BrightFg | CyanFg
+// BrightWhite foreground color (97).
+func (v Value) BrightWhite() Value {
+ v.cc = colorConfig(v.cc.color().BrightWhite()) | v.cc.resetColor()
return v
}
-func (v value) BrightWhite() Value {
- v.color = (v.color &^ maskFg) | BrightFg | WhiteFg
+// Other colors.
+//
+// Index of pre-defined 8-bit foreground color from 0 to 255 (38;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 30–37 m)
+// 8- 15: high intensity colors (as in ESC [ 90–97 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func (v Value) Index(n ColorIndex) Value {
+ v.cc = colorConfig(v.cc.color().Index(n)) | v.cc.resetColor()
return v
}
-func (v value) Index(n uint8) Value {
- v.color = (v.color &^ maskFg) | (Color(n) << shiftFg) | flagFg
+// Gray from 0 to 24.
+func (v Value) Gray(n GrayIndex) Value {
+ v.cc = colorConfig(v.cc.color().Gray(n)) | v.cc.resetColor()
return v
}
-func (v value) Gray(n uint8) Value {
- if n > 23 {
- n = 23
- }
- v.color = (v.color &^ maskFg) | (Color(232+n) << shiftFg) | flagFg
+// Background colors
+//
+// BgBlack background color (40).
+func (v Value) BgBlack() Value {
+ v.cc = colorConfig(v.cc.color().BgBlack()) | v.cc.resetColor()
return v
}
-func (v value) BgBlack() Value {
- v.color = (v.color &^ maskBg) | BlackBg
+// BgRed background color (41).
+func (v Value) BgRed() Value {
+ v.cc = colorConfig(v.cc.color().BgRed()) | v.cc.resetColor()
return v
}
-func (v value) BgRed() Value {
- v.color = (v.color &^ maskBg) | RedBg
+// BgGreen background color (42).
+func (v Value) BgGreen() Value {
+ v.cc = colorConfig(v.cc.color().BgGreen()) | v.cc.resetColor()
return v
}
-func (v value) BgGreen() Value {
- v.color = (v.color &^ maskBg) | GreenBg
+// BgYellow background color (43).
+func (v Value) BgYellow() Value {
+ v.cc = colorConfig(v.cc.color().BgYellow()) | v.cc.resetColor()
return v
}
-func (v value) BgYellow() Value {
- v.color = (v.color &^ maskBg) | YellowBg
+// BgBlue background color (44).
+func (v Value) BgBlue() Value {
+ v.cc = colorConfig(v.cc.color().BgBlue()) | v.cc.resetColor()
return v
}
-func (v value) BgBrown() Value {
- return v.BgYellow()
+// BgMagenta background color (45).
+func (v Value) BgMagenta() Value {
+ v.cc = colorConfig(v.cc.color().BgMagenta()) | v.cc.resetColor()
+ return v
}
-func (v value) BgBlue() Value {
- v.color = (v.color &^ maskBg) | BlueBg
+// BgCyan background color (46).
+func (v Value) BgCyan() Value {
+ v.cc = colorConfig(v.cc.color().BgCyan()) | v.cc.resetColor()
return v
}
-func (v value) BgMagenta() Value {
- v.color = (v.color &^ maskBg) | MagentaBg
+// BgWhite background color (47).
+func (v Value) BgWhite() Value {
+ v.cc = colorConfig(v.cc.color().BgWhite()) | v.cc.resetColor()
return v
}
-func (v value) BgCyan() Value {
- v.color = (v.color &^ maskBg) | CyanBg
+// Bright background colors.
+//
+// BgBrightBlack background color (100).
+func (v Value) BgBrightBlack() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightBlack()) | v.cc.resetColor()
return v
}
-func (v value) BgWhite() Value {
- v.color = (v.color &^ maskBg) | WhiteBg
+// BgBrightRed background color (101).
+func (v Value) BgBrightRed() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightRed()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightBlack() Value {
- v.color = (v.color &^ maskBg) | BrightBg | BlackBg
+// BgBrightGreen background color (102).
+func (v Value) BgBrightGreen() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightGreen()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightRed() Value {
- v.color = (v.color &^ maskBg) | BrightBg | RedBg
+// BgBrightYellow background color (103).
+func (v Value) BgBrightYellow() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightYellow()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightGreen() Value {
- v.color = (v.color &^ maskBg) | BrightBg | GreenBg
+// BgBrightBlue background color (104).
+func (v Value) BgBrightBlue() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightBlue()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightYellow() Value {
- v.color = (v.color &^ maskBg) | BrightBg | YellowBg
+// BgBrightMagenta background color (105).
+func (v Value) BgBrightMagenta() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightMagenta()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightBlue() Value {
- v.color = (v.color &^ maskBg) | BrightBg | BlueBg
+// BgBrightCyan background color (106).
+func (v Value) BgBrightCyan() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightCyan()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightMagenta() Value {
- v.color = (v.color &^ maskBg) | BrightBg | MagentaBg
+// BgBrightWhite background color (107).
+func (v Value) BgBrightWhite() Value {
+ v.cc = colorConfig(v.cc.color().BgBrightWhite()) | v.cc.resetColor()
return v
}
-func (v value) BgBrightCyan() Value {
- v.color = (v.color &^ maskBg) | BrightBg | CyanBg
+// Other background colors.
+//
+// BgIndex of 8-bit pre-defined background color from 0 to 255 (48;5;n).
+//
+// 0- 7: standard colors (as in ESC [ 40–47 m)
+// 8- 15: high intensity colors (as in ESC [100–107 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func (v Value) BgIndex(n ColorIndex) Value {
+ v.cc = colorConfig(v.cc.color().BgIndex(n)) | v.cc.resetColor()
return v
}
-func (v value) BgBrightWhite() Value {
- v.color = (v.color &^ maskBg) | BrightBg | WhiteBg
+// BgGray from 0 to 24.
+func (v Value) BgGray(n GrayIndex) Value {
+ v.cc = colorConfig(v.cc.color().BgGray(n)) | v.cc.resetColor()
return v
}
-func (v value) BgIndex(n uint8) Value {
- v.color = (v.color &^ maskBg) | (Color(n) << shiftBg) | flagBg
+// Special colorization method.
+//
+// Colorize removes existing colors and formats of the argument and applies
+// given.
+func (v Value) Colorize(color Color) Value {
+ v.cc = colorConfig(color) | v.cc.resetColor()
return v
}
-func (v value) BgGray(n uint8) Value {
- if n > 23 {
- n = 23
+// Hyperlinks feature
+//
+// Hyperlink with given target and parameters. If hyperlinks feature is
+// disabled, then the 'arg' argument dropped and the 'target' used instead,
+// inheriting all colors and format from the 'arg' (if it's a Colored).
+//
+// See https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+// for details about the hyperlinks feature.
+//
+// The Hyperlink doesn't escape the target and the parameters. They should be
+// checked and escaped before. See HyperlinkEscape function.
+//
+// See also HyperlinkID function.
+//
+// For a simple example
+//
+// val.Hyperlink("http://example.com")
+//
+// and an example with ID
+//
+// val.Hyperlink("http://example.com", aurora.HyperlinkID("10"))
+//
+// Successive calls replace previously set target and parameters.
+func (v Value) Hyperlink(target string, params ...HyperlinkParam) Value {
+ if !v.cc.hyperlinksEnbaled() {
+ v.value = target // drop value, use the target
+ v.hyperlink = &hyperlink{
+ target: target, // keep for the HyperlinkTarget method
+ }
+ return v
}
- v.color = (v.color &^ maskBg) | (Color(232+n) << shiftBg) | flagBg
+ if v.hyperlink == nil {
+ v.hyperlink = new(hyperlink)
+ }
+ v.hyperlink.target = target
+ v.hyperlink.params = params
return v
}
-func (v value) Colorize(color Color) Value {
- v.color = color
- return v
+// HyperlinkTarget if any.
+func (v Value) HyperlinkTarget() (target string) {
+ if v.hyperlink != nil {
+ return v.hyperlink.target
+ }
+ return // nothing
+}
+
+// HyperlinkParams if any.
+func (v Value) HyperlinkParams() (params []HyperlinkParam) {
+ if v.hyperlink != nil {
+ return v.hyperlink.params
+ }
+ return // nil
}
diff --git a/value_test.go b/value_test.go
index 4553277..5043763 100644
--- a/value_test.go
+++ b/value_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -38,306 +38,340 @@ package aurora
import (
"fmt"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestValue_String(t *testing.T) {
- var v Value
+ var au *Aurora
// colorized
- v = value{"x", 0, 0}
- if x := v.String(); x != "x" {
- t.Errorf("(value).String: want %q, got %q", "x", x)
- }
- v = value{"x", BlackFg, RedBg}
- want := "\033[0;30mx\033[0;41m"
- if got := v.String(); want != got {
- t.Errorf("(value).String: want %q, got %q", want, got)
- }
+ au = New()
+ assert.Equal(t, "x", au.Clear("x").String())
+ assert.Equal(t, "\033[30;41mx\033[0m", au.Black("x").BgRed().String())
// clear
- v = valueClear{"x"}
- if x := v.String(); x != "x" {
- t.Errorf("(value).String: want %q, got %q", "x", x)
- }
-
+ au = New(WithColors(false))
+ assert.Equal(t, "x", au.Black("x").BgRed().String())
+ // colorized hyperlink
+ au = New()
+ assert.Equal(t, `]8;;http://example.com`+
+ `\[31mx[0m]8;;\`,
+ au.Red("x").Hyperlink("http://example.com").String())
+ // clear hyperlink
+ assert.Equal(t, `]8;;http://example.com\x]8;;\`,
+ au.Clear("x").Hyperlink("http://example.com").String())
}
func TestValue_Color(t *testing.T) {
// colorized
- if (value{"", RedFg, 0}).Color() != RedFg {
- t.Error("wrong color")
- }
- // clear
- if (valueClear{0}).Color() != 0 {
- t.Error("wrong color")
- }
+ assert.Equal(t, RedFg, New().Red("x").Color())
+ // clear, also red
+ assert.Equal(t, RedFg, New().Red("x").Color())
}
func TestValue_Value(t *testing.T) {
// colorized
- if (value{"x", RedFg, BlueBg}).Value() != "x" {
- t.Error("wrong value")
- }
- // clear
- if (valueClear{"x"}).Value() != "x" {
- t.Error("wrong value")
- }
-}
-
-func TestValue_Bleach(t *testing.T) {
- // colorized
- if (value{"x", RedFg, BlueBg}).Bleach() != (value{value: "x"}) {
- t.Error("wrong bleached")
- }
+ assert.Equal(t, "x", New().Clear("x").Value())
// clear
- if (valueClear{"x"}).Bleach() != (valueClear{"x"}) {
- t.Error("wrong bleached")
- }
+ assert.Equal(t, "x", New(WithColors(false)).Black("x").BgRed().Value())
}
-func TestValue_Format(t *testing.T) {
- var v Value
- var want, got string
- //
+func TestValue_Reset(t *testing.T) {
// colorized
- //
- v = value{3.14, RedFg, BlueBg}
- got = fmt.Sprintf("%+1.3g", v)
- want = "\033[0;31m" + fmt.Sprintf("%+1.3g", 3.14) + "\033[0;44m"
- if want != got {
- t.Errorf("Format: want %q, got %q", want, got)
- }
- //
- var utf8Verb = "%+1.3世" // verb that fit more then 1 byte
- got = fmt.Sprintf(utf8Verb, v)
- want = "\033[0;31m" + fmt.Sprintf(utf8Verb, 3.14) + "\033[0;44m"
- if want != got {
- t.Errorf("Format: want %q, got %q", want, got)
- }
- //
+ var au = New()
+ assert.Equal(t, Value{
+ cc: au.cc,
+ value: "x",
+ }, au.Red("x").BgBlack().Reset())
// clear
- //
- v = valueClear{3.14}
- got = fmt.Sprintf("%+1.3g", v)
- want = fmt.Sprintf("%+1.3g", 3.14)
- if want != got {
- t.Errorf("Format: want %q, got %q", want, got)
- }
- //
- got = fmt.Sprintf(utf8Verb, v)
- want = fmt.Sprintf(utf8Verb, 3.14)
- if want != got {
- t.Errorf("Format: want %q, got %q", want, got)
- }
+ au = New(WithColors(false))
+ assert.Equal(t, Value{
+ cc: au.cc,
+ value: "x",
+ }, au.Red("x").BgBlack().Reset())
+ // a hyperlink
+ au = New()
+ assert.Equal(t,
+ Value{
+ cc: au.cc,
+ value: "x",
+ }, au.Red("x").
+ BgBlack().
+ Hyperlink("http://example.com/path", HyperlinkID("10")).
+ Reset())
}
-func Test_tail(t *testing.T) {
+func TestValue_Clear(t *testing.T) {
// colorized
- if (value{"x", 0, BlueBg}).tail() != BlueBg {
- t.Error("wrong tail color")
- }
+ var au = New()
+ assert.Equal(t, Value{
+ cc: au.cc,
+ value: "x",
+ }, au.Red("x").BgBlack().Clear())
// clear
- if (valueClear{"x"}).tail() != 0 {
- t.Error("wrong tail color")
- }
+ au = New(WithColors(false))
+ assert.Equal(t, Value{
+ cc: au.cc,
+ value: "x",
+ }, au.Red("x").BgBlack().Clear())
+ // a hyperlink
+ au = New()
+ assert.EqualValues(t,
+ Value{
+ cc: au.cc,
+ value: "x",
+ hyperlink: &hyperlink{
+ target: "http://example.com/path",
+ params: []HyperlinkParam{{
+ Key: HyperlinkIDKey,
+ Value: "10",
+ }},
+ },
+ }, au.Red("x").
+ BgBlack().
+ Hyperlink("http://example.com/path", HyperlinkID("10")).
+ Clear())
}
-func Test_setTail(t *testing.T) {
+func TestValue_Format(t *testing.T) {
// colorized
- if (value{"x", 0, 0}).setTail(RedFg) != (value{"x", 0, RedFg}) {
- t.Error("wrong setTail behavior")
- }
+ var au = New()
+ assert.Equal(t, "\033[31;44m"+fmt.Sprintf("%+1.3g", 3.14)+"\033[0m",
+ fmt.Sprintf("%+1.3g", au.Red(3.14).BgBlue()))
+ const utf8Verb = "%+1.3世" // verb that fit more then 1 byte
+ assert.Equal(t, "\033[31;44m"+"%!世(float64=+3.14)"+"\033[0m",
+ fmt.Sprintf(utf8Verb, au.Red(3.14).BgBlue())) //nolint
// clear
- if (valueClear{"x"}).setTail(RedFg) != (valueClear{"x"}) {
- t.Error("wrong setTail behavior")
- }
+ au = New(WithColors(false))
+ assert.Equal(t, fmt.Sprintf("%+1.3g", 3.14),
+ fmt.Sprintf("%+1.3g", au.Red(3.14).BgBlue()))
+ assert.Equal(t, "%!世(float64=+3.14)",
+ fmt.Sprintf(utf8Verb, au.Red(3.14).BgBlue())) //nolint
}
func TestValue_colors(t *testing.T) {
- test := func(name string, v Value, clr Color) {
+ var test = func(name string, v Value, clr Color) {
t.Helper()
- if c := v.Color(); c != clr {
- t.Errorf("wrong color for %s: want %d, got %d", name, clr, c)
- }
+ assert.Equal(t, clr, v.Color())
}
// colorized
- test("Reset", Reset("x"), 0)
- test("Bold", Bold("x"), BoldFm)
- test("Faint", Faint("x"), FaintFm)
- test("DoublyUnderline", DoublyUnderline("x"), DoublyUnderlineFm)
- test("Fraktur & Yellow", Yellow(Fraktur("x")), FrakturFm|YellowFg)
- test("Italic", Italic("x"), ItalicFm)
- test("Underline", Underline("x"), UnderlineFm)
- test("SlowBlink", SlowBlink("x"), SlowBlinkFm)
- test("RapidBlink", RapidBlink("x"), RapidBlinkFm)
- test("Blink", Blink("x"), BlinkFm)
- test("Reverse", Reverse("x"), ReverseFm)
- test("Inverse", Inverse("x"), InverseFm)
- test("Conceal", Conceal("x"), ConcealFm)
- test("Hidden", Hidden("x"), HiddenFm)
- test("CrossedOut", CrossedOut("x"), CrossedOutFm)
- test("StrikeThrough", StrikeThrough("x"), StrikeThroughFm)
- test("Framed", Framed("x"), FramedFm)
- test("Encircled", Encircled("x"), EncircledFm)
- test("Overlined", Overlined("x"), OverlinedFm)
- test("Black", Black("x"), BlackFg)
- test("Red", Red("x"), RedFg)
- test("Green", Green("x"), GreenFg)
- test("Yellow", Yellow("x"), YellowFg)
- test("Brown", Brown("x"), BrownFg)
- test("Blue", Blue("x"), BlueFg)
- test("Magenta", Magenta("x"), MagentaFg)
- test("Cyan", Cyan("x"), CyanFg)
- test("White", White("x"), WhiteFg)
- test("BrightBlack", BrightBlack("x"), BrightFg|BlackFg)
- test("BrightRed", BrightRed("x"), BrightFg|RedFg)
- test("BrightGreen", BrightGreen("x"), BrightFg|GreenFg)
- test("BrightYellow", BrightYellow("x"), BrightFg|YellowFg)
- test("BrightBlue", BrightBlue("x"), BrightFg|BlueFg)
- test("BrightMagenta", BrightMagenta("x"), BrightFg|MagentaFg)
- test("BrightCyan", BrightCyan("x"), BrightFg|CyanFg)
- test("BrightWhite", BrightWhite("x"), BrightFg|WhiteFg)
- test("Index", Index(178, "x"), (Color(178)<<shiftFg)|flagFg)
- test("Gray", Gray(14, "x"), (Color(14+232)<<shiftFg)|flagFg)
- test("BgBlack", BgBlack("x"), BlackBg)
- test("BgRed", BgRed("x"), RedBg)
- test("BgGreen", BgGreen("x"), GreenBg)
- test("BgYellow", BgYellow("x"), YellowBg)
- test("BgBrown", BgBrown("x"), BrownBg)
- test("BgBlue", BgBlue("x"), BlueBg)
- test("BgMagenta", BgMagenta("x"), MagentaBg)
- test("BgCyan", BgCyan("x"), CyanBg)
- test("BgWhite", BgWhite("x"), WhiteBg)
- test("BgBrightBlack", BgBrightBlack("x"), BrightBg|BlackBg)
- test("BgBrightRed", BgBrightRed("x"), BrightBg|RedBg)
- test("BgBrightGreen", BgBrightGreen("x"), BrightBg|GreenBg)
- test("BgBrightYellow", BgBrightYellow("x"), BrightBg|YellowBg)
- test("BgBrightBlue", BgBrightBlue("x"), BrightBg|BlueBg)
- test("BgBrightMagenta", BgBrightMagenta("x"), BrightBg|MagentaBg)
- test("BgBrightCyan", BgBrightCyan("x"), BrightBg|CyanBg)
- test("BgBrightWhite", BgBrightWhite("x"), BrightBg|WhiteBg)
- test("BgIndex", BgIndex(187, "x"), Color(187)<<shiftBg|flagBg)
- test("BgGray", BgGray(15, "x"), Color(232+15)<<shiftBg|flagBg)
- test("Colorize", Colorize("x", RedFg|BlueBg|BrightBg|BoldFm),
+ var au = New()
+ test("Reset", au.Reset("x"), 0)
+ test("Clear", au.Clear("x"), 0)
+ test("Bold", au.Bold("x"), BoldFm)
+ test("Faint", au.Faint("x"), FaintFm)
+ test("DoublyUnderline", au.DoublyUnderline("x"), DoublyUnderlineFm)
+ test("Fraktur & au.Yellow", Yellow(Fraktur("x")), FrakturFm|YellowFg)
+ test("Italic", au.Italic("x"), ItalicFm)
+ test("Underline", au.Underline("x"), UnderlineFm)
+ test("SlowBlink", au.SlowBlink("x"), SlowBlinkFm)
+ test("RapidBlink", au.RapidBlink("x"), RapidBlinkFm)
+ test("Blink", au.Blink("x"), BlinkFm)
+ test("Reverse", au.Reverse("x"), ReverseFm)
+ test("Inverse", au.Inverse("x"), InverseFm)
+ test("Conceal", au.Conceal("x"), ConcealFm)
+ test("Hidden", au.Hidden("x"), HiddenFm)
+ test("CrossedOut", au.CrossedOut("x"), CrossedOutFm)
+ test("StrikeThrough", au.StrikeThrough("x"), StrikeThroughFm)
+ test("Framed", au.Framed("x"), FramedFm)
+ test("Encircled", au.Encircled("x"), EncircledFm)
+ test("Overlined", au.Overlined("x"), OverlinedFm)
+ test("Black", au.Black("x"), BlackFg)
+ test("Red", au.Red("x"), RedFg)
+ test("Green", au.Green("x"), GreenFg)
+ test("Yellow", au.Yellow("x"), YellowFg)
+ test("Blue", au.Blue("x"), BlueFg)
+ test("Magenta", au.Magenta("x"), MagentaFg)
+ test("Cyan", au.Cyan("x"), CyanFg)
+ test("White", au.White("x"), WhiteFg)
+ test("BrightBlack", au.BrightBlack("x"), BrightFg|BlackFg)
+ test("BrightRed", au.BrightRed("x"), BrightFg|RedFg)
+ test("BrightGreen", au.BrightGreen("x"), BrightFg|GreenFg)
+ test("BrightYellow", au.BrightYellow("x"), BrightFg|YellowFg)
+ test("BrightBlue", au.BrightBlue("x"), BrightFg|BlueFg)
+ test("BrightMagenta", au.BrightMagenta("x"), BrightFg|MagentaFg)
+ test("BrightCyan", au.BrightCyan("x"), BrightFg|CyanFg)
+ test("BrightWhite", au.BrightWhite("x"), BrightFg|WhiteFg)
+ test("Index", au.Index(178, "x"), (Color(178)<<shiftFg)|flagFg)
+ test("Gray", au.Gray(14, "x"), (Color(14+232)<<shiftFg)|flagFg)
+ test("BgBlack", au.BgBlack("x"), BlackBg)
+ test("BgRed", au.BgRed("x"), RedBg)
+ test("BgGreen", au.BgGreen("x"), GreenBg)
+ test("BgYellow", au.BgYellow("x"), YellowBg)
+ test("BgBlue", au.BgBlue("x"), BlueBg)
+ test("BgMagenta", au.BgMagenta("x"), MagentaBg)
+ test("BgCyan", au.BgCyan("x"), CyanBg)
+ test("BgWhite", au.BgWhite("x"), WhiteBg)
+ test("BgBrightBlack", au.BgBrightBlack("x"), BrightBg|BlackBg)
+ test("BgBrightRed", au.BgBrightRed("x"), BrightBg|RedBg)
+ test("BgBrightGreen", au.BgBrightGreen("x"), BrightBg|GreenBg)
+ test("BgBrightYellow", au.BgBrightYellow("x"), BrightBg|YellowBg)
+ test("BgBrightBlue", au.BgBrightBlue("x"), BrightBg|BlueBg)
+ test("BgBrightMagenta", au.BgBrightMagenta("x"), BrightBg|MagentaBg)
+ test("BgBrightCyan", au.BgBrightCyan("x"), BrightBg|CyanBg)
+ test("BgBrightWhite", au.BgBrightWhite("x"), BrightBg|WhiteBg)
+ test("BgIndex", au.BgIndex(187, "x"), Color(187)<<shiftBg|flagBg)
+ test("BgGray", au.BgGray(15, "x"), Color(232+15)<<shiftBg|flagBg)
+ test("Colorize", au.Colorize("x", RedFg|BlueBg|BrightBg|BoldFm),
RedFg|BlueBg|BrightBg|BoldFm)
// clear
- test("Reset", valueClear{"x"}.Reset(), 0)
- test("Bold", valueClear{"x"}.Bold(), 0)
- test("Faint", valueClear{"x"}.Faint(), 0)
- test("DoublyUnderline", valueClear{"x"}.DoublyUnderline(), 0)
- test("Fraktur & Yellow", valueClear{"x"}.Fraktur(), 0)
- test("Italic", valueClear{"x"}.Italic(), 0)
- test("Underline", valueClear{"x"}.Underline(), 0)
- test("SlowBlink", valueClear{"x"}.SlowBlink(), 0)
- test("RapidBlink", valueClear{"x"}.RapidBlink(), 0)
- test("Blink", valueClear{"x"}.Blink(), 0)
- test("Reverse", valueClear{"x"}.Reverse(), 0)
- test("Inverse", valueClear{"x"}.Inverse(), 0)
- test("Conceal", valueClear{"x"}.Conceal(), 0)
- test("Hidden", valueClear{"x"}.Hidden(), 0)
- test("CrossedOut", valueClear{"x"}.CrossedOut(), 0)
- test("StrikeThrough", valueClear{"x"}.StrikeThrough(), 0)
- test("Framed", valueClear{"x"}.Framed(), 0)
- test("Encircled", valueClear{"x"}.Encircled(), 0)
- test("Overlined", valueClear{"x"}.Overlined(), 0)
- test("Black", valueClear{"x"}.Black(), 0)
- test("Red", valueClear{"x"}.Red(), 0)
- test("Green", valueClear{"x"}.Green(), 0)
- test("Yellow", valueClear{"x"}.Yellow(), 0)
- test("Brown", valueClear{"x"}.Brown(), 0)
- test("Blue", valueClear{"x"}.Blue(), 0)
- test("Magenta", valueClear{"x"}.Magenta(), 0)
- test("Cyan", valueClear{"x"}.Cyan(), 0)
- test("White", valueClear{"x"}.White(), 0)
- test("BrightBlack", valueClear{"x"}.BrightBlack(), 0)
- test("BrightRed", valueClear{"x"}.BrightRed(), 0)
- test("BrightGreen", valueClear{"x"}.BrightGreen(), 0)
- test("BrightYellow", valueClear{"x"}.BrightYellow(), 0)
- test("BrightBlue", valueClear{"x"}.BrightBlue(), 0)
- test("BrightMagenta", valueClear{"x"}.BrightMagenta(), 0)
- test("BrightCyan", valueClear{"x"}.BrightCyan(), 0)
- test("BrightWhite", valueClear{"x"}.BrightWhite(), 0)
- test("Index", valueClear{"x"}.Index(178), 0)
- test("Gray", valueClear{"x"}.Gray(14), 0)
- test("BgBlack", valueClear{"x"}.BgBlack(), 0)
- test("BgRed", valueClear{"x"}.BgRed(), 0)
- test("BgGreen", valueClear{"x"}.BgGreen(), 0)
- test("BgYellow", valueClear{"x"}.BgYellow(), 0)
- test("BgBrown", valueClear{"x"}.BgBrown(), 0)
- test("BgBlue", valueClear{"x"}.BgBlue(), 0)
- test("BgMagenta", valueClear{"x"}.BgMagenta(), 0)
- test("BgCyan", valueClear{"x"}.BgCyan(), 0)
- test("BgWhite", valueClear{"x"}.BgWhite(), 0)
- test("BgBrightBlack", valueClear{"x"}.BgBrightBlack(), 0)
- test("BgBrightRed", valueClear{"x"}.BgBrightRed(), 0)
- test("BgBrightGreen", valueClear{"x"}.BgBrightGreen(), 0)
- test("BgBrightYellow", valueClear{"x"}.BgBrightYellow(), 0)
- test("BgBrightBlue", valueClear{"x"}.BgBrightBlue(), 0)
- test("BgBrightMagenta", valueClear{"x"}.BgBrightMagenta(), 0)
- test("BgBrightCyan", valueClear{"x"}.BgBrightCyan(), 0)
- test("BgBrightWhite", valueClear{"x"}.BgBrightWhite(), 0)
- test("BgIndex", valueClear{"x"}.BgIndex(187), 0)
- test("BgGray", valueClear{"x"}.BgGray(15), 0)
- test("Colorize", valueClear{"x"}.Colorize(RedFg|BlueBg|BrightBg|BoldFm), 0)
+ au = New(WithColors(false))
+ test("Reset", au.Clear("x").Reset(), 0)
+ test("Clear", au.Bold("x").Clear(), 0)
+ test("Bold", au.Clear("x").Bold(), 0)
+ test("Faint", au.Clear("x").Faint(), 0)
+ test("DoublyUnderline", au.Clear("x").DoublyUnderline(), 0)
+ test("Fraktur & Yellow", au.Clear("x").Fraktur(), 0)
+ test("Italic", au.Clear("x").Italic(), 0)
+ test("Underline", au.Clear("x").Underline(), 0)
+ test("SlowBlink", au.Clear("x").SlowBlink(), 0)
+ test("RapidBlink", au.Clear("x").RapidBlink(), 0)
+ test("Blink", au.Clear("x").Blink(), 0)
+ test("Reverse", au.Clear("x").Reverse(), 0)
+ test("Inverse", au.Clear("x").Inverse(), 0)
+ test("Conceal", au.Clear("x").Conceal(), 0)
+ test("Hidden", au.Clear("x").Hidden(), 0)
+ test("CrossedOut", au.Clear("x").CrossedOut(), 0)
+ test("StrikeThrough", au.Clear("x").StrikeThrough(), 0)
+ test("Framed", au.Clear("x").Framed(), 0)
+ test("Encircled", au.Clear("x").Encircled(), 0)
+ test("Overlined", au.Clear("x").Overlined(), 0)
+ test("Black", au.Clear("x").Black(), 0)
+ test("Red", au.Clear("x").Red(), 0)
+ test("Green", au.Clear("x").Green(), 0)
+ test("Yellow", au.Clear("x").Yellow(), 0)
+ test("Blue", au.Clear("x").Blue(), 0)
+ test("Magenta", au.Clear("x").Magenta(), 0)
+ test("Cyan", au.Clear("x").Cyan(), 0)
+ test("White", au.Clear("x").White(), 0)
+ test("BrightBlack", au.Clear("x").BrightBlack(), 0)
+ test("BrightRed", au.Clear("x").BrightRed(), 0)
+ test("BrightGreen", au.Clear("x").BrightGreen(), 0)
+ test("BrightYellow", au.Clear("x").BrightYellow(), 0)
+ test("BrightBlue", au.Clear("x").BrightBlue(), 0)
+ test("BrightMagenta", au.Clear("x").BrightMagenta(), 0)
+ test("BrightCyan", au.Clear("x").BrightCyan(), 0)
+ test("BrightWhite", au.Clear("x").BrightWhite(), 0)
+ test("Index", au.Clear("x").Index(178), 0)
+ test("Gray", au.Clear("x").Gray(14), 0)
+ test("BgBlack", au.Clear("x").BgBlack(), 0)
+ test("BgRed", au.Clear("x").BgRed(), 0)
+ test("BgGreen", au.Clear("x").BgGreen(), 0)
+ test("BgYellow", au.Clear("x").BgYellow(), 0)
+ test("BgBlue", au.Clear("x").BgBlue(), 0)
+ test("BgMagenta", au.Clear("x").BgMagenta(), 0)
+ test("BgCyan", au.Clear("x").BgCyan(), 0)
+ test("BgWhite", au.Clear("x").BgWhite(), 0)
+ test("BgBrightBlack", au.Clear("x").BgBrightBlack(), 0)
+ test("BgBrightRed", au.Clear("x").BgBrightRed(), 0)
+ test("BgBrightGreen", au.Clear("x").BgBrightGreen(), 0)
+ test("BgBrightYellow", au.Clear("x").BgBrightYellow(), 0)
+ test("BgBrightBlue", au.Clear("x").BgBrightBlue(), 0)
+ test("BgBrightMagenta", au.Clear("x").BgBrightMagenta(), 0)
+ test("BgBrightCyan", au.Clear("x").BgBrightCyan(), 0)
+ test("BgBrightWhite", au.Clear("x").BgBrightWhite(), 0)
+ test("BgIndex", au.Clear("x").BgIndex(187), 0)
+ test("BgGray", au.Clear("x").BgGray(15), 0)
+ test("Colorize", au.Clear("x").Colorize(RedFg|BlueBg|BrightBg|BoldFm), 0)
// change
- test("Reset", Bold("x").Reset(), 0)
- test("Bold", Faint("x").Bold(), BoldFm)
- test("Faint", Bold("x").Faint(), FaintFm)
- test("DoublyUnderline", Reset("x").DoublyUnderline(), DoublyUnderlineFm)
- test("Fraktur & Yellow", Reset("x").Yellow().Fraktur(), FrakturFm|YellowFg)
- test("Italic", Reset("x").Italic(), ItalicFm)
- test("Underline", Reset("x").Underline(), UnderlineFm)
- test("SlowBlink", RapidBlink("x").SlowBlink(), SlowBlinkFm)
- test("RapidBlink", SlowBlink("x").RapidBlink(), RapidBlinkFm)
- test("Blink", Reset("x").Blink(), BlinkFm)
- test("Reverse", Reset("x").Reverse(), ReverseFm)
- test("Inverse", Reset("x").Inverse(), InverseFm)
- test("Conceal", Reset("x").Conceal(), ConcealFm)
- test("Hidden", Reset("x").Hidden(), HiddenFm)
- test("CrossedOut", Reset("x").CrossedOut(), CrossedOutFm)
- test("StrikeThrough", Reset("x").StrikeThrough(), StrikeThroughFm)
- test("Framed", Reset("x").Framed(), FramedFm)
- test("Encircled", Reset("x").Encircled(), EncircledFm)
- test("Overlined", Reset("x").Overlined(), OverlinedFm)
- test("Black", Reset("x").Black(), BlackFg)
- test("Red", Reset("x").Red(), RedFg)
- test("Green", Reset("x").Green(), GreenFg)
- test("Yellow", Reset("x").Yellow(), YellowFg)
- test("Brown", Reset("x").Brown(), BrownFg)
- test("Blue", Reset("x").Blue(), BlueFg)
- test("Magenta", Reset("x").Magenta(), MagentaFg)
- test("Cyan", Reset("x").Cyan(), CyanFg)
- test("White", Reset("x").White(), WhiteFg)
- test("BrightBlack", Reset("x").BrightBlack(), BrightFg|BlackFg)
- test("BrightRed", Reset("x").BrightRed(), BrightFg|RedFg)
- test("BrightGreen", Reset("x").BrightGreen(), BrightFg|GreenFg)
- test("BrightYellow", Reset("x").BrightYellow(), BrightFg|YellowFg)
- test("BrightBlue", Reset("x").BrightBlue(), BrightFg|BlueFg)
- test("BrightMagenta", Reset("x").BrightMagenta(), BrightFg|MagentaFg)
- test("BrightCyan", Reset("x").BrightCyan(), BrightFg|CyanFg)
- test("BrightWhite", Reset("x").BrightWhite(), BrightFg|WhiteFg)
- test("Index", Reset("x").Index(178), (Color(178)<<shiftFg)|flagFg)
- test("Gray", Reset("x").Gray(14), (Color(14+232)<<shiftFg)|flagFg)
- test("BgBlack", Reset("x").BgBlack(), BlackBg)
- test("BgRed", Reset("x").BgRed(), RedBg)
- test("BgGreen", Reset("x").BgGreen(), GreenBg)
- test("BgYellow", Reset("x").BgYellow(), YellowBg)
- test("BgBrown", Reset("x").BgBrown(), BrownBg)
- test("BgBlue", Reset("x").BgBlue(), BlueBg)
- test("BgMagenta", Reset("x").BgMagenta(), MagentaBg)
- test("BgCyan", Reset("x").BgCyan(), CyanBg)
- test("BgWhite", Reset("x").BgWhite(), WhiteBg)
- test("BgBrightBlack", Reset("x").BgBrightBlack(), BrightBg|BlackBg)
- test("BgBrightRed", Reset("x").BgBrightRed(), BrightBg|RedBg)
- test("BgBrightGreen", Reset("x").BgBrightGreen(), BrightBg|GreenBg)
- test("BgBrightYellow", Reset("x").BgBrightYellow(), BrightBg|YellowBg)
- test("BgBrightBlue", Reset("x").BgBrightBlue(), BrightBg|BlueBg)
- test("BgBrightMagenta", Reset("x").BgBrightMagenta(), BrightBg|MagentaBg)
- test("BgBrightCyan", Reset("x").BgBrightCyan(), BrightBg|CyanBg)
- test("BgBrightWhite", Reset("x").BgBrightWhite(), BrightBg|WhiteBg)
- test("BgIndex", Reset("x").BgIndex(187), Color(187)<<shiftBg|flagBg)
- test("BgGray", Reset("x").BgGray(15), Color(232+15)<<shiftBg|flagBg)
- test("Colorize", Reset("x").Colorize(RedFg|BlueBg|BrightBg|BoldFm),
+ au = New()
+ test("Reset", au.Bold("x").Reset(), 0)
+ test("Clear", au.Bold("x").Clear(), 0)
+ test("Bold", au.Faint("x").Bold(), BoldFm)
+ test("Faint", au.Bold("x").Faint(), FaintFm)
+ test("DoublyUnderline", au.Reset("x").DoublyUnderline(), DoublyUnderlineFm)
+ test("Fraktur & Yellow", au.Reset("x").Yellow().Fraktur(), FrakturFm|YellowFg)
+ test("Italic", au.Reset("x").Italic(), ItalicFm)
+ test("Underline", au.Reset("x").Underline(), UnderlineFm)
+ test("SlowBlink", au.RapidBlink("x").SlowBlink(), SlowBlinkFm)
+ test("RapidBlink", au.SlowBlink("x").RapidBlink(), RapidBlinkFm)
+ test("Blink", au.Reset("x").Blink(), BlinkFm)
+ test("Reverse", au.Reset("x").Reverse(), ReverseFm)
+ test("Inverse", au.Reset("x").Inverse(), InverseFm)
+ test("Conceal", au.Reset("x").Conceal(), ConcealFm)
+ test("Hidden", au.Reset("x").Hidden(), HiddenFm)
+ test("CrossedOut", au.Reset("x").CrossedOut(), CrossedOutFm)
+ test("StrikeThrough", au.Reset("x").StrikeThrough(), StrikeThroughFm)
+ test("Framed", au.Reset("x").Framed(), FramedFm)
+ test("Encircled", au.Reset("x").Encircled(), EncircledFm)
+ test("Overlined", au.Reset("x").Overlined(), OverlinedFm)
+ test("Black", au.Reset("x").Black(), BlackFg)
+ test("Red", au.Reset("x").Red(), RedFg)
+ test("Green", au.Reset("x").Green(), GreenFg)
+ test("Yellow", au.Reset("x").Yellow(), YellowFg)
+ test("Blue", au.Reset("x").Blue(), BlueFg)
+ test("Magenta", au.Reset("x").Magenta(), MagentaFg)
+ test("Cyan", au.Reset("x").Cyan(), CyanFg)
+ test("White", au.Reset("x").White(), WhiteFg)
+ test("BrightBlack", au.Reset("x").BrightBlack(), BrightFg|BlackFg)
+ test("BrightRed", au.Reset("x").BrightRed(), BrightFg|RedFg)
+ test("BrightGreen", au.Reset("x").BrightGreen(), BrightFg|GreenFg)
+ test("BrightYellow", au.Reset("x").BrightYellow(), BrightFg|YellowFg)
+ test("BrightBlue", au.Reset("x").BrightBlue(), BrightFg|BlueFg)
+ test("BrightMagenta", au.Reset("x").BrightMagenta(), BrightFg|MagentaFg)
+ test("BrightCyan", au.Reset("x").BrightCyan(), BrightFg|CyanFg)
+ test("BrightWhite", au.Reset("x").BrightWhite(), BrightFg|WhiteFg)
+ test("Index", au.Reset("x").Index(178), (Color(178)<<shiftFg)|flagFg)
+ test("Gray", au.Reset("x").Gray(14), (Color(14+232)<<shiftFg)|flagFg)
+ test("BgBlack", au.Reset("x").BgBlack(), BlackBg)
+ test("BgRed", au.Reset("x").BgRed(), RedBg)
+ test("BgGreen", au.Reset("x").BgGreen(), GreenBg)
+ test("BgYellow", au.Reset("x").BgYellow(), YellowBg)
+ test("BgBlue", au.Reset("x").BgBlue(), BlueBg)
+ test("BgMagenta", au.Reset("x").BgMagenta(), MagentaBg)
+ test("BgCyan", au.Reset("x").BgCyan(), CyanBg)
+ test("BgWhite", au.Reset("x").BgWhite(), WhiteBg)
+ test("BgBrightBlack", au.Reset("x").BgBrightBlack(), BrightBg|BlackBg)
+ test("BgBrightRed", au.Reset("x").BgBrightRed(), BrightBg|RedBg)
+ test("BgBrightGreen", au.Reset("x").BgBrightGreen(), BrightBg|GreenBg)
+ test("BgBrightYellow", au.Reset("x").BgBrightYellow(), BrightBg|YellowBg)
+ test("BgBrightBlue", au.Reset("x").BgBrightBlue(), BrightBg|BlueBg)
+ test("BgBrightMagenta", au.Reset("x").BgBrightMagenta(), BrightBg|MagentaBg)
+ test("BgBrightCyan", au.Reset("x").BgBrightCyan(), BrightBg|CyanBg)
+ test("BgBrightWhite", au.Reset("x").BgBrightWhite(), BrightBg|WhiteBg)
+ test("BgIndex", au.Reset("x").BgIndex(187), Color(187)<<shiftBg|flagBg)
+ test("BgGray", au.Reset("x").BgGray(15), Color(232+15)<<shiftBg|flagBg)
+ test("Colorize", au.Reset("x").Colorize(RedFg|BlueBg|BrightBg|BoldFm),
RedFg|BlueBg|BrightBg|BoldFm)
// overflow
- test("Gray", Reset("x").Gray(151), Color(232+23)<<shiftFg|flagFg)
- test("BgGray", Reset("x").BgGray(115), Color(232+23)<<shiftBg|flagBg)
+ test("Gray", au.Reset("x").Gray(151), Color(232+23)<<shiftFg|flagFg)
+ test("BgGray", au.Reset("x").BgGray(115), Color(232+23)<<shiftBg|flagBg)
+}
+
+func TestValue_hyperlinks(t *testing.T) {
+ const target = "http://example.com/path?query=value"
+ var (
+ au = New()
+ params = []HyperlinkParam{
+ {
+ Key: HyperlinkIDKey,
+ Value: "10",
+ },
+ {
+ Key: "another",
+ Value: "custom",
+ },
+ }
+ val Value
+ want string
+ )
+ val = au.Red("x").Hyperlink(target, HyperlinkID("10"),
+ HyperlinkParam{"another", "custom"})
+ assert.Equal(t, target, val.HyperlinkTarget())
+ assert.EqualValues(t, params, val.HyperlinkParams())
+ want = `]8;id=10:another=custom;http://example.com/path?` +
+ `query=value\[31mx[0m]8;;\`
+ assert.Equal(t, want, val.String())
+
+ // wrap a hyperlink
+ au = New(WithHyperlinks(false))
+ want = `[31mhttp://example.com[0m`
+ val = au.Red("x").Hyperlink("http://example.com")
+ assert.Equal(t, want, val.String())
+ assert.Equal(t, "http://example.com", val.HyperlinkTarget())
+ assert.Equal(t, "http://example.com", val.Value())
+
+ // no target, no parameters
+ val = au.Clear("x")
+ assert.Equal(t, "", val.HyperlinkTarget())
+ assert.Nil(t, val.HyperlinkParams())
}
diff --git a/wrap.go b/wrap.go
index 44e1aa6..16f6786 100644
--- a/wrap.go
+++ b/wrap.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -35,34 +35,34 @@
package aurora
-// Colorize wraps given value into Value with
-// given colors. For example
+// DefaultColorizer is global colorizer that used for package root color
+// methods.
+var DefaultColorizer = New(WithColors(true), WithHyperlinks(true))
+
+// Colorize wraps given value into Value with given colors. For example
//
-// s := Colorize("some", BlueFg|GreenBg|BoldFm)
+// var s = Colorize("some", BlueFg|GreenBg|BoldFm)
//
-// returns a Value with blue foreground, green
-// background and bold. Unlike functions like
-// Red/BgBlue/Bold etc. This function clears
-// all previous colors and formats. Thus
+// returns a Value with blue foreground, green background and bold. Unlike
+// functions like Red/BgBlue/Bold etc. This function clears all previous colors
+// and formats. Thus
//
-// s := Colorize(Red("some"), BgBlue)
+// var s = Colorize(Red("some"), BgBlue)
//
-// clears red color from value
+// clears red color from value.
func Colorize(arg interface{}, color Color) Value {
- if val, ok := arg.(value); ok {
- val.color = color
- return val
- }
- return value{arg, color, 0}
+ return DefaultColorizer.Colorize(arg, color)
}
-// Reset wraps given argument returning Value
-// without formats and colors.
+// Reset wraps given argument returning Value without formats, colors and links.
func Reset(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Reset()
- }
- return value{value: arg}
+ return DefaultColorizer.Reset(arg)
+}
+
+// Clear wraps given argument returning Value without formats and colors. But
+// preserving links.
+func Clear(arg interface{}) Value {
+ return DefaultColorizer.Clear(arg)
}
//
@@ -71,142 +71,93 @@ func Reset(arg interface{}) Value {
// Bold or increased intensity (1).
func Bold(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Bold()
- }
- return value{value: arg, color: BoldFm}
+ return DefaultColorizer.Bold(arg)
}
-// Faint decreases intensity (2).
-// The Faint rejects the Bold.
+// Faint decreases intensity (2). The Faint rejects the Bold.
func Faint(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Faint()
- }
- return value{value: arg, color: FaintFm}
+ return DefaultColorizer.Faint(arg)
}
-// DoublyUnderline or Bold off, double-underline
-// per ECMA-48 (21).
+// DoublyUnderline or Bold off, double-underline per ECMA-48 (21).
func DoublyUnderline(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.DoublyUnderline()
- }
- return value{value: arg, color: DoublyUnderlineFm}
+ return DefaultColorizer.DoublyUnderline(arg)
}
// Fraktur is rarely supported (20).
func Fraktur(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Fraktur()
- }
- return value{value: arg, color: FrakturFm}
+ return DefaultColorizer.Fraktur(arg)
}
-// Italic is not widely supported, sometimes
-// treated as inverse (3).
+// Italic is not widely supported, sometimes treated as inverse (3).
func Italic(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Italic()
- }
- return value{value: arg, color: ItalicFm}
+ return DefaultColorizer.Italic(arg)
}
// Underline (4).
func Underline(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Underline()
- }
- return value{value: arg, color: UnderlineFm}
+ return DefaultColorizer.Underline(arg)
}
-// SlowBlink makes text blink less than
-// 150 per minute (5).
+// SlowBlink makes text blink less than 150 per minute (5).
func SlowBlink(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.SlowBlink()
- }
- return value{value: arg, color: SlowBlinkFm}
+ return DefaultColorizer.SlowBlink(arg)
}
-// RapidBlink makes text blink 150+ per
-// minute. It is not widely supported (6).
+// RapidBlink makes text blink 150+ per minute. It is not widely supported (6).
func RapidBlink(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.RapidBlink()
- }
- return value{value: arg, color: RapidBlinkFm}
+ return DefaultColorizer.RapidBlink(arg)
}
// Blink is alias for the SlowBlink.
func Blink(arg interface{}) Value {
- return SlowBlink(arg)
+ return DefaultColorizer.Blink(arg)
}
-// Reverse video, swap foreground and
-// background colors (7).
+// Reverse video, swap foreground and background colors (7).
func Reverse(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Reverse()
- }
- return value{value: arg, color: ReverseFm}
+ return DefaultColorizer.Reverse(arg)
}
// Inverse is alias for the Reverse
func Inverse(arg interface{}) Value {
- return Reverse(arg)
+ return DefaultColorizer.Inverse(arg)
}
-// Conceal hides text, preserving an ability to select
-// the text and copy it. It is not widely supported (8).
+// Conceal hides text, preserving an ability to select the text and copy it. It
+// is not widely supported (8).
func Conceal(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Conceal()
- }
- return value{value: arg, color: ConcealFm}
+ return DefaultColorizer.Conceal(arg)
}
// Hidden is alias for the Conceal
func Hidden(arg interface{}) Value {
- return Conceal(arg)
+ return DefaultColorizer.Hidden(arg)
}
-// CrossedOut makes characters legible, but
-// marked for deletion (9).
+// CrossedOut makes characters legible, but marked for deletion (9).
func CrossedOut(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.CrossedOut()
- }
- return value{value: arg, color: CrossedOutFm}
+ return DefaultColorizer.CrossedOut(arg)
}
// StrikeThrough is alias for the CrossedOut.
func StrikeThrough(arg interface{}) Value {
- return CrossedOut(arg)
+ return DefaultColorizer.StrikeThrough(arg)
}
// Framed (51).
func Framed(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Framed()
- }
- return value{value: arg, color: FramedFm}
+ return DefaultColorizer.Framed(arg)
}
// Encircled (52).
func Encircled(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Encircled()
- }
- return value{value: arg, color: EncircledFm}
+ return DefaultColorizer.Encircled(arg)
}
// Overlined (53).
func Overlined(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Overlined()
- }
- return value{value: arg, color: OverlinedFm}
+ return DefaultColorizer.Overlined(arg)
}
//
@@ -216,73 +167,42 @@ func Overlined(arg interface{}) Value {
// Black foreground color (30)
func Black(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Black()
- }
- return value{value: arg, color: BlackFg}
+ return DefaultColorizer.Black(arg)
}
// Red foreground color (31)
func Red(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Red()
- }
- return value{value: arg, color: RedFg}
+ return DefaultColorizer.Red(arg)
}
// Green foreground color (32)
func Green(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Green()
- }
- return value{value: arg, color: GreenFg}
+ return DefaultColorizer.Green(arg)
}
// Yellow foreground color (33)
func Yellow(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Yellow()
- }
- return value{value: arg, color: YellowFg}
-}
-
-// Brown foreground color (33)
-//
-// Deprecated: use Yellow instead, following specification
-func Brown(arg interface{}) Value {
- return Yellow(arg)
+ return DefaultColorizer.Yellow(arg)
}
// Blue foreground color (34)
func Blue(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Blue()
- }
- return value{value: arg, color: BlueFg}
+ return DefaultColorizer.Blue(arg)
}
// Magenta foreground color (35)
func Magenta(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Magenta()
- }
- return value{value: arg, color: MagentaFg}
+ return DefaultColorizer.Magenta(arg)
}
// Cyan foreground color (36)
func Cyan(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Cyan()
- }
- return value{value: arg, color: CyanFg}
+ return DefaultColorizer.Cyan(arg)
}
// White foreground color (37)
func White(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.White()
- }
- return value{value: arg, color: WhiteFg}
+ return DefaultColorizer.White(arg)
}
//
@@ -291,96 +211,61 @@ func White(arg interface{}) Value {
// BrightBlack foreground color (90)
func BrightBlack(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightBlack()
- }
- return value{value: arg, color: BrightFg | BlackFg}
+ return DefaultColorizer.BrightBlack(arg)
}
// BrightRed foreground color (91)
func BrightRed(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightRed()
- }
- return value{value: arg, color: BrightFg | RedFg}
+ return DefaultColorizer.BrightRed(arg)
}
// BrightGreen foreground color (92)
func BrightGreen(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightGreen()
- }
- return value{value: arg, color: BrightFg | GreenFg}
+ return DefaultColorizer.BrightGreen(arg)
}
// BrightYellow foreground color (93)
func BrightYellow(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightYellow()
- }
- return value{value: arg, color: BrightFg | YellowFg}
+ return DefaultColorizer.BrightYellow(arg)
}
// BrightBlue foreground color (94)
func BrightBlue(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightBlue()
- }
- return value{value: arg, color: BrightFg | BlueFg}
+ return DefaultColorizer.BrightBlue(arg)
}
// BrightMagenta foreground color (95)
func BrightMagenta(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightMagenta()
- }
- return value{value: arg, color: BrightFg | MagentaFg}
+ return DefaultColorizer.BrightMagenta(arg)
}
// BrightCyan foreground color (96)
func BrightCyan(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightCyan()
- }
- return value{value: arg, color: BrightFg | CyanFg}
+ return DefaultColorizer.BrightCyan(arg)
}
// BrightWhite foreground color (97)
func BrightWhite(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BrightWhite()
- }
- return value{value: arg, color: BrightFg | WhiteFg}
+ return DefaultColorizer.BrightWhite(arg)
}
//
// Other
//
-// Index of pre-defined 8-bit foreground color
-// from 0 to 255 (38;5;n).
-//
-// 0- 7: standard colors (as in ESC [ 30–37 m)
-// 8- 15: high intensity colors (as in ESC [ 90–97 m)
-// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
-// 232-255: grayscale from black to white in 24 steps
+// Index of pre-defined 8-bit foreground color from 0 to 255 (38;5;n).
//
-func Index(n uint8, arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Index(n)
- }
- return value{value: arg, color: (Color(n) << shiftFg) | flagFg}
+// 0- 7: standard colors (as in ESC [ 30–37 m)
+// 8- 15: high intensity colors (as in ESC [ 90–97 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func Index(n ColorIndex, arg interface{}) Value {
+ return DefaultColorizer.Index(n, arg)
}
// Gray from 0 to 24.
-func Gray(n uint8, arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.Gray(n)
- }
- if n > 23 {
- n = 23
- }
- return value{value: arg, color: (Color(232+n) << shiftFg) | flagFg}
+func Gray(n GrayIndex, arg interface{}) Value {
+ return DefaultColorizer.Gray(n, arg)
}
//
@@ -390,73 +275,42 @@ func Gray(n uint8, arg interface{}) Value {
// BgBlack background color (40)
func BgBlack(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBlack()
- }
- return value{value: arg, color: BlackBg}
+ return DefaultColorizer.BgBlack(arg)
}
// BgRed background color (41)
func BgRed(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgRed()
- }
- return value{value: arg, color: RedBg}
+ return DefaultColorizer.BgRed(arg)
}
// BgGreen background color (42)
func BgGreen(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgGreen()
- }
- return value{value: arg, color: GreenBg}
+ return DefaultColorizer.BgGreen(arg)
}
// BgYellow background color (43)
func BgYellow(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgYellow()
- }
- return value{value: arg, color: YellowBg}
-}
-
-// BgBrown background color (43)
-//
-// Deprecated: use BgYellow instead, following specification
-func BgBrown(arg interface{}) Value {
- return BgYellow(arg)
+ return DefaultColorizer.BgYellow(arg)
}
// BgBlue background color (44)
func BgBlue(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBlue()
- }
- return value{value: arg, color: BlueBg}
+ return DefaultColorizer.BgBlue(arg)
}
// BgMagenta background color (45)
func BgMagenta(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgMagenta()
- }
- return value{value: arg, color: MagentaBg}
+ return DefaultColorizer.BgMagenta(arg)
}
// BgCyan background color (46)
func BgCyan(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgCyan()
- }
- return value{value: arg, color: CyanBg}
+ return DefaultColorizer.BgCyan(arg)
}
// BgWhite background color (47)
func BgWhite(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgWhite()
- }
- return value{value: arg, color: WhiteBg}
+ return DefaultColorizer.BgWhite(arg)
}
//
@@ -465,94 +319,113 @@ func BgWhite(arg interface{}) Value {
// BgBrightBlack background color (100)
func BgBrightBlack(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightBlack()
- }
- return value{value: arg, color: BrightBg | BlackBg}
+ return DefaultColorizer.BgBrightBlack(arg)
}
// BgBrightRed background color (101)
func BgBrightRed(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightRed()
- }
- return value{value: arg, color: BrightBg | RedBg}
+ return DefaultColorizer.BgBrightRed(arg)
}
// BgBrightGreen background color (102)
func BgBrightGreen(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightGreen()
- }
- return value{value: arg, color: BrightBg | GreenBg}
+ return DefaultColorizer.BgBrightGreen(arg)
}
// BgBrightYellow background color (103)
func BgBrightYellow(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightYellow()
- }
- return value{value: arg, color: BrightBg | YellowBg}
+ return DefaultColorizer.BgBrightYellow(arg)
}
// BgBrightBlue background color (104)
func BgBrightBlue(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightBlue()
- }
- return value{value: arg, color: BrightBg | BlueBg}
+ return DefaultColorizer.BgBrightBlue(arg)
}
// BgBrightMagenta background color (105)
func BgBrightMagenta(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightMagenta()
- }
- return value{value: arg, color: BrightBg | MagentaBg}
+ return DefaultColorizer.BgBrightMagenta(arg)
}
// BgBrightCyan background color (106)
func BgBrightCyan(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightCyan()
- }
- return value{value: arg, color: BrightBg | CyanBg}
+ return DefaultColorizer.BgBrightCyan(arg)
}
// BgBrightWhite background color (107)
func BgBrightWhite(arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgBrightWhite()
- }
- return value{value: arg, color: BrightBg | WhiteBg}
+ return DefaultColorizer.BgBrightWhite(arg)
}
//
// Other
//
-// BgIndex of 8-bit pre-defined background color
-// from 0 to 255 (48;5;n).
-//
-// 0- 7: standard colors (as in ESC [ 40–47 m)
-// 8- 15: high intensity colors (as in ESC [100–107 m)
-// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
-// 232-255: grayscale from black to white in 24 steps
+// BgIndex of 8-bit pre-defined background color from 0 to 255 (48;5;n).
//
-func BgIndex(n uint8, arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgIndex(n)
- }
- return value{value: arg, color: (Color(n) << shiftBg) | flagBg}
+// 0- 7: standard colors (as in ESC [ 40–47 m)
+// 8- 15: high intensity colors (as in ESC [100–107 m)
+// 16-231: 6 × 6 × 6 cube (216 colors): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
+// 232-255: grayscale from black to white in 24 steps
+func BgIndex(n ColorIndex, arg interface{}) Value {
+ return DefaultColorizer.BgIndex(n, arg)
}
// BgGray from 0 to 24.
-func BgGray(n uint8, arg interface{}) Value {
- if val, ok := arg.(Value); ok {
- return val.BgGray(n)
- }
- if n > 23 {
- n = 23
- }
- return value{value: arg, color: (Color(n+232) << shiftBg) | flagBg}
+func BgGray(n GrayIndex, arg interface{}) Value {
+ return DefaultColorizer.BgGray(n, arg)
+}
+
+//
+// Hyperlinks feature
+//
+
+// Hyperlink with given target and parameters. If hyperlinks feature is
+// disabled, then the 'arg' argument dropped and the 'target' used instead
+// inheriting all colors and format from the 'arg' (if it's a Colored).
+//
+// See https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
+// for details about the hyperlinks feature.
+//
+// The Hyperlink doesn't escape the target and the params. They should be
+// checked and escaped before.
+//
+// See also HyperlinkID function.
+//
+// For a simple example
+//
+// au.Hyperlink("Example", "http://example.com")
+//
+// and an example with ID
+//
+// au.Hyperlink("Example", "http://example.com", aurora.HyperlinkID("10"))
+func Hyperlink(arg interface{}, target string, params ...HyperlinkParam) Value {
+ return DefaultColorizer.Hyperlink(arg, target, params...)
+}
+
+// HyperlinkTarget of the argument if it's a Value.
+func HyperlinkTarget(arg interface{}) (target string) {
+ return DefaultColorizer.HyperlinkTarget(arg)
+}
+
+// HyperlinkParams of the argument if it's a Value.
+func HyperlinkParams(arg interface{}) (params []HyperlinkParam) {
+ return DefaultColorizer.HyperlinkParams(arg)
+}
+
+// Sprintf allows to use Value as format. For example
+//
+// var v = Sprintf(Red("total: +3.5f points"), Blue(3.14))
+//
+// In this case "total:" and "points" will be red, but
+// 3.14 will be blue. But, in another example
+//
+// var v = Sprintf(Red("total: +3.5f points"), 3.14)
+//
+// full string will be red. And no way to clear 3.14 to default format and
+// color.
+//
+// It applies own configurations to all given Values.
+func Sprintf(format interface{}, args ...interface{}) string {
+ return DefaultColorizer.Sprintf(format, args...)
}
diff --git a/wrap_test.go b/wrap_test.go
index ddd31b3..e2e644a 100644
--- a/wrap_test.go
+++ b/wrap_test.go
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2020 The Aurora Authors. All rights reserved.
+// Copyright (c) 2016-2022 The Aurora Authors. All rights reserved.
// This program is free software. It comes without any warranty,
// to the extent permitted by applicable law. You can redistribute
// it and/or modify it under the terms of the Unlicense. See LICENSE
@@ -37,6 +37,8 @@ package aurora
import (
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func testFunc(t *testing.T, name string, v Value, clr Color) {
@@ -46,9 +48,6 @@ func testFunc(t *testing.T, name string, v Value, clr Color) {
} else if str != "x" {
t.Errorf("%s wrong value: '%v', expected 'x'", name, v.Value())
}
- if !isTail(v, 0) {
- t.Errorf("%s wrong tail: %d", name, v.tail())
- }
if !isColor(v, clr) {
t.Errorf("%s wrong color: %d, want: %d", name, v.Color(), clr)
}
@@ -60,6 +59,12 @@ func Test_Reset(t *testing.T) {
0)
}
+func Test_Clear(t *testing.T) {
+ testFunc(t, "Clear", Clear("x"), 0)
+ testFunc(t, "Complex Clear", Clear(DoublyUnderline(Underline("x"))),
+ 0)
+}
+
func Test_Bold(t *testing.T) {
testFunc(t, "Bold", Bold("x"), BoldFm)
testFunc(t, "Complex Bold", Bold(Italic(Red("x"))),
@@ -192,12 +197,6 @@ func Test_Yellow(t *testing.T) {
YellowFg|BoldFm|BrightBg|MagentaBg)
}
-func Test_Brown(t *testing.T) {
- testFunc(t, "Brown", Brown("x"), BrownFg)
- testFunc(t, "Complex Brown", Brown(BgBrightBlue("x").Bold()),
- BrownFg|BrightBg|BlueBg|BoldFm)
-}
-
func Test_Blue(t *testing.T) {
testFunc(t, "Blue", Blue("x"), BlueFg)
testFunc(t, "Complex Blue", Blue(Fraktur("x").Underline()),
@@ -306,12 +305,6 @@ func Test_BgYellow(t *testing.T) {
YellowBg|BlinkFm)
}
-func Test_BgBrown(t *testing.T) {
- testFunc(t, "BgBrown", BgBrown("x"), BrownBg)
- testFunc(t, "Complex BgBrown", BgBrown(Hidden("x")),
- BrownBg|HiddenFm)
-}
-
func Test_BgBlue(t *testing.T) {
testFunc(t, "BgBlue", BgBlue("x"), BlueBg)
testFunc(t, "Complex BgBlue", BgBlue(Framed("x")),
@@ -408,3 +401,53 @@ func Test_bigGray(t *testing.T) {
testFunc(t, "Gray", Gray(115, "x"), Color(232+23)<<shiftFg|flagFg)
testFunc(t, "BgGray", BgGray(215, "x"), Color(232+23)<<shiftBg|flagBg)
}
+
+func Test_Hyperlink(t *testing.T) {
+ assert.EqualValues(t,
+ Value{
+ value: "Example",
+ cc: DefaultColorizer.cc,
+ hyperlink: &hyperlink{
+ target: "http://example.com",
+ params: []HyperlinkParam{{
+ Key: "id",
+ Value: "10",
+ }},
+ },
+ },
+ Hyperlink("Example", "http://example.com", HyperlinkID("10")))
+
+ assert.EqualValues(t,
+ Value{
+ value: "Example",
+ cc: DefaultColorizer.cc | colorConfig(RedFg),
+ hyperlink: &hyperlink{
+ target: "http://example.com",
+ params: []HyperlinkParam{{
+ Key: "id",
+ Value: "10",
+ }},
+ },
+ },
+ Hyperlink(Red("Example"), "http://example.com", HyperlinkID("10")))
+}
+
+func Test_HyperlinkTarget(t *testing.T) {
+ assert.Equal(t, "", HyperlinkTarget("Example"))
+ assert.Equal(t, "http://example.com",
+ HyperlinkTarget(Hyperlink(
+ Red("Example"), "http://example.com", HyperlinkID("10")),
+ ))
+}
+
+func Test_HyperlinkParams(t *testing.T) {
+ assert.Equal(t, HyperlinkParams(nil), HyperlinkParams("Example"))
+ assert.EqualValues(t,
+ []HyperlinkParam{{
+ Key: "id",
+ Value: "10",
+ }},
+ HyperlinkParams(Hyperlink(
+ Red("Example"), "http://example.com", HyperlinkID("10")),
+ ))
+}
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/gocode/src/github.com/logrusorgru/aurora/config.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/logrusorgru/aurora/config_test.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/logrusorgru/aurora/go.sum -rw-r--r-- root/root /usr/share/gocode/src/github.com/logrusorgru/aurora/hyperlinks.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/logrusorgru/aurora/hyperlinks_test.go
No differences were encountered in the control files