Skip to content

Commit 5430f4d

Browse files
authored
Merge pull request #225 from mum4k/release-0-11-0
## [0.11.0] - 7-Mar-2020 #### Breaking API changes - Termdash now requires at least Go version 1.11. ### Added - New [`tcell`](https://github.com/gdamore/tcell) based terminal implementation which implements the `terminalapi.Terminal` interface. - tcell implementation supports two initialization `Option`s: - `ColorMode` the terminal color output mode (defaults to 256 color mode) - `ClearStyle` the foreground and background color style to use when clearing the screen (defaults to the global ColorDefault for both foreground and background)
2 parents 68bf056 + 6c6d276 commit 5430f4d

File tree

13 files changed

+1211
-23
lines changed

13 files changed

+1211
-23
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
language: go
22
go:
3-
- 1.10.x
43
- 1.11.x
54
- 1.12.x
5+
- 1.13.x
66
- stable
77
script:
88
- go get -t ./...

CHANGELOG.md

+22-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [0.11.0] - 7-Mar-2020
11+
12+
#### Breaking API changes
13+
14+
- Termdash now requires at least Go version 1.11.
15+
16+
### Added
17+
18+
- New [`tcell`](https://github.com/gdamore/tcell) based terminal implementation
19+
which implements the `terminalapi.Terminal` interface.
20+
- tcell implementation supports two initialization `Option`s:
21+
- `ColorMode` the terminal color output mode (defaults to 256 color mode)
22+
- `ClearStyle` the foreground and background color style to use when clearing
23+
the screen (defaults to the global ColorDefault for both foreground and
24+
background)
25+
26+
### Fixed
27+
28+
- Improved test coverage of the `Gauge` widget.
29+
1030
## [0.10.0] - 5-Jun-2019
1131

1232
### Added
@@ -295,7 +315,8 @@ identifiers shouldn't be used externally.
295315
- The Gauge widget.
296316
- The Text widget.
297317

298-
[unreleased]: https://github.com/mum4k/termdash/compare/v0.10.0...devel
318+
[unreleased]: https://github.com/mum4k/termdash/compare/v0.11.0...devel
319+
[0.11.0]: https://github.com/mum4k/termdash/compare/v0.10.0...v0.11.0
299320
[0.10.0]: https://github.com/mum4k/termdash/compare/v0.9.1...v0.10.0
300321
[0.9.1]: https://github.com/mum4k/termdash/compare/v0.9.0...v0.9.1
301322
[0.9.0]: https://github.com/mum4k/termdash/compare/v0.8.0...v0.9.0

internal/numbers/numbers_test.go

+2-14
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ func TestZeroBeforeDecimal(t *testing.T) {
8383
}
8484
}
8585

86-
// Copied from the math package of Go 1.10 for backwards compatibility with Go
87-
// 1.8 where the math.Round function doesn't exist yet.
86+
// Copied from the Go's math package, file all_test.go.
8887
func tolerance(a, b, e float64) bool {
8988
// Multiplying by e here can underflow denormal values to zero.
9089
// Check a==b so that at least if a and b are small and identical
@@ -107,18 +106,7 @@ func tolerance(a, b, e float64) bool {
107106
}
108107
return d < e
109108
}
110-
func close(a, b float64) bool { return tolerance(a, b, 1e-14) }
111-
func veryclose(a, b float64) bool { return tolerance(a, b, 4e-16) }
112-
func soclose(a, b, e float64) bool { return tolerance(a, b, e) }
113-
func alike(a, b float64) bool {
114-
switch {
115-
case math.IsNaN(a) && math.IsNaN(b):
116-
return true
117-
case a == b:
118-
return math.Signbit(a) == math.Signbit(b)
119-
}
120-
return false
121-
}
109+
func veryclose(a, b float64) bool { return tolerance(a, b, 4e-16) }
122110

123111
func TestMinMax(t *testing.T) {
124112
tests := []struct {

termdashdemo/termdashdemo.go

+26-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ package main
1818

1919
import (
2020
"context"
21+
"flag"
2122
"fmt"
23+
"log"
2224
"math"
2325
"math/rand"
2426
"sync"
@@ -31,6 +33,7 @@ import (
3133
"github.com/mum4k/termdash/container/grid"
3234
"github.com/mum4k/termdash/keyboard"
3335
"github.com/mum4k/termdash/linestyle"
36+
"github.com/mum4k/termdash/terminal/tcell"
3437
"github.com/mum4k/termdash/terminal/termbox"
3538
"github.com/mum4k/termdash/terminal/terminalapi"
3639
"github.com/mum4k/termdash/widgets/barchart"
@@ -466,8 +469,30 @@ func contLayout(w *widgets) ([]container.Option, error) {
466469
// rootID is the ID assigned to the root container.
467470
const rootID = "root"
468471

472+
// Terminal implementations
473+
const (
474+
termboxTerminal = "termbox"
475+
tcellTerminal = "tcell"
476+
)
477+
469478
func main() {
470-
t, err := termbox.New(termbox.ColorMode(terminalapi.ColorMode256))
479+
terminalPtr := flag.String("terminal",
480+
"termbox",
481+
"The terminal implementation to use. Available implementations are 'termbox' and 'tcell' (default = termbox).")
482+
flag.Parse()
483+
484+
var t terminalapi.Terminal
485+
var err error
486+
switch terminal := *terminalPtr; terminal {
487+
case termboxTerminal:
488+
t, err = termbox.New(termbox.ColorMode(terminalapi.ColorMode256))
489+
case tcellTerminal:
490+
t, err = tcell.New(tcell.ColorMode(terminalapi.ColorMode256))
491+
default:
492+
log.Fatalf("Unknown terminal implementation '%s' specified. Please choose between 'termbox' and 'tcell'.", terminal)
493+
return
494+
}
495+
471496
if err != nil {
472497
panic(err)
473498
}

terminal/tcell/cell_options.go

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2020 Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tcell
16+
17+
import (
18+
"github.com/gdamore/tcell"
19+
"github.com/mum4k/termdash/cell"
20+
"github.com/mum4k/termdash/terminal/terminalapi"
21+
)
22+
23+
// cellColor converts termdash cell color to the tcell format.
24+
func cellColor(c cell.Color) tcell.Color {
25+
return tcell.Color(c&0x1ff) - 1
26+
}
27+
28+
// fixColor converts the target color for the current color mode
29+
func fixColor(c tcell.Color, colorMode terminalapi.ColorMode) tcell.Color {
30+
if c == tcell.ColorDefault {
31+
return c
32+
}
33+
switch colorMode {
34+
case terminalapi.ColorModeNormal:
35+
c %= tcell.Color(16)
36+
case terminalapi.ColorMode256:
37+
c %= tcell.Color(256)
38+
case terminalapi.ColorMode216:
39+
c %= tcell.Color(216)
40+
c += tcell.Color(16)
41+
case terminalapi.ColorModeGrayscale:
42+
c %= tcell.Color(24)
43+
c += tcell.Color(232)
44+
default:
45+
c = tcell.ColorDefault
46+
}
47+
return c
48+
}
49+
50+
// cellOptsToStyle converts termdash cell color to the tcell format.
51+
func cellOptsToStyle(opts *cell.Options, colorMode terminalapi.ColorMode) tcell.Style {
52+
st := tcell.StyleDefault
53+
54+
fg := cellColor(opts.FgColor)
55+
bg := cellColor(opts.BgColor)
56+
57+
fg = fixColor(fg, colorMode)
58+
bg = fixColor(bg, colorMode)
59+
60+
st = st.Foreground(fg).Background(bg)
61+
return st
62+
}

terminal/tcell/cell_options_test.go

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2020 Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package tcell
16+
17+
import (
18+
"testing"
19+
20+
"github.com/gdamore/tcell"
21+
"github.com/mum4k/termdash/cell"
22+
"github.com/mum4k/termdash/terminal/terminalapi"
23+
)
24+
25+
func TestCellColor(t *testing.T) {
26+
tests := []struct {
27+
color cell.Color
28+
want tcell.Color
29+
}{
30+
{cell.ColorDefault, tcell.ColorDefault},
31+
{cell.ColorBlack, tcell.ColorBlack},
32+
{cell.ColorRed, tcell.ColorMaroon},
33+
{cell.ColorGreen, tcell.ColorGreen},
34+
{cell.ColorYellow, tcell.ColorOlive},
35+
{cell.ColorBlue, tcell.ColorNavy},
36+
{cell.ColorMagenta, tcell.ColorPurple},
37+
{cell.ColorCyan, tcell.ColorTeal},
38+
{cell.ColorWhite, tcell.ColorSilver},
39+
{cell.ColorNumber(42), tcell.Color(42)},
40+
}
41+
42+
for _, tc := range tests {
43+
t.Run(tc.color.String(), func(t *testing.T) {
44+
got := cellColor(tc.color)
45+
if got != tc.want {
46+
t.Errorf("cellColor(%v) => got %v, want %v", tc.color, got, tc.want)
47+
}
48+
})
49+
}
50+
}
51+
52+
func TestFixColor(t *testing.T) {
53+
tests := []struct {
54+
colorMode terminalapi.ColorMode
55+
color cell.Color
56+
want tcell.Color
57+
}{
58+
// See https://jonasjacek.github.io/colors/ for a good reference of all 256 xterm colors
59+
// All 256 colors
60+
{terminalapi.ColorMode256, cell.ColorDefault, tcell.ColorDefault},
61+
{terminalapi.ColorMode256, cell.ColorBlack, tcell.ColorBlack},
62+
{terminalapi.ColorMode256, cell.ColorRed, tcell.ColorMaroon},
63+
{terminalapi.ColorMode256, cell.ColorGreen, tcell.ColorGreen},
64+
{terminalapi.ColorMode256, cell.ColorYellow, tcell.ColorOlive},
65+
{terminalapi.ColorMode256, cell.ColorBlue, tcell.ColorNavy},
66+
{terminalapi.ColorMode256, cell.ColorMagenta, tcell.ColorPurple},
67+
{terminalapi.ColorMode256, cell.ColorCyan, tcell.ColorTeal},
68+
{terminalapi.ColorMode256, cell.ColorWhite, tcell.ColorSilver},
69+
{terminalapi.ColorMode256, cell.ColorNumber(42), tcell.Color(42)},
70+
// 8 system colors
71+
{terminalapi.ColorModeNormal, cell.ColorDefault, tcell.ColorDefault},
72+
{terminalapi.ColorModeNormal, cell.ColorBlack, tcell.ColorBlack},
73+
{terminalapi.ColorModeNormal, cell.ColorRed, tcell.ColorMaroon},
74+
{terminalapi.ColorModeNormal, cell.ColorGreen, tcell.ColorGreen},
75+
{terminalapi.ColorModeNormal, cell.ColorYellow, tcell.ColorOlive},
76+
{terminalapi.ColorModeNormal, cell.ColorBlue, tcell.ColorNavy},
77+
{terminalapi.ColorModeNormal, cell.ColorMagenta, tcell.ColorPurple},
78+
{terminalapi.ColorModeNormal, cell.ColorCyan, tcell.ColorTeal},
79+
{terminalapi.ColorModeNormal, cell.ColorWhite, tcell.ColorSilver},
80+
{terminalapi.ColorModeNormal, cell.ColorNumber(42), tcell.Color(10)},
81+
// Grayscale colors (all the grey colours from 231 to 255)
82+
{terminalapi.ColorModeGrayscale, cell.ColorDefault, tcell.ColorDefault},
83+
{terminalapi.ColorModeGrayscale, cell.ColorBlack, tcell.Color232},
84+
{terminalapi.ColorModeGrayscale, cell.ColorRed, tcell.Color233},
85+
{terminalapi.ColorModeGrayscale, cell.ColorGreen, tcell.Color234},
86+
{terminalapi.ColorModeGrayscale, cell.ColorYellow, tcell.Color235},
87+
{terminalapi.ColorModeGrayscale, cell.ColorBlue, tcell.Color236},
88+
{terminalapi.ColorModeGrayscale, cell.ColorMagenta, tcell.Color237},
89+
{terminalapi.ColorModeGrayscale, cell.ColorCyan, tcell.Color238},
90+
{terminalapi.ColorModeGrayscale, cell.ColorWhite, tcell.Color239},
91+
{terminalapi.ColorModeGrayscale, cell.ColorNumber(42), tcell.Color(250)},
92+
// 216 colors (16 to 231)
93+
{terminalapi.ColorMode216, cell.ColorDefault, tcell.ColorDefault},
94+
{terminalapi.ColorMode216, cell.ColorBlack, tcell.Color16},
95+
{terminalapi.ColorMode216, cell.ColorRed, tcell.Color17},
96+
{terminalapi.ColorMode216, cell.ColorGreen, tcell.Color18},
97+
{terminalapi.ColorMode216, cell.ColorYellow, tcell.Color19},
98+
{terminalapi.ColorMode216, cell.ColorBlue, tcell.Color20},
99+
{terminalapi.ColorMode216, cell.ColorMagenta, tcell.Color21},
100+
{terminalapi.ColorMode216, cell.ColorCyan, tcell.Color22},
101+
{terminalapi.ColorMode216, cell.ColorWhite, tcell.Color23},
102+
{terminalapi.ColorMode216, cell.ColorNumber(42), tcell.Color(58)},
103+
// Unknown color mode
104+
{-1, cell.ColorRed, tcell.ColorDefault},
105+
}
106+
107+
for _, tc := range tests {
108+
t.Run(tc.colorMode.String()+"_"+tc.color.String(), func(t *testing.T) {
109+
color := cellColor(tc.color)
110+
got := fixColor(color, tc.colorMode)
111+
if got != tc.want {
112+
t.Errorf("fixColor(%v_%v), => got %v, want %v", tc.colorMode, tc.color, got, tc.want)
113+
}
114+
})
115+
}
116+
}
117+
118+
func TestCellOptsToStyle(t *testing.T) {
119+
tests := []struct {
120+
colorMode terminalapi.ColorMode
121+
opts cell.Options
122+
want tcell.Style
123+
}{
124+
{
125+
colorMode: terminalapi.ColorMode256,
126+
opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
127+
want: tcell.StyleDefault.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
128+
},
129+
{
130+
colorMode: terminalapi.ColorModeNormal,
131+
opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
132+
want: tcell.StyleDefault.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
133+
},
134+
{
135+
colorMode: terminalapi.ColorModeGrayscale,
136+
opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
137+
want: tcell.StyleDefault.Foreground(tcell.Color239).Background(tcell.Color232),
138+
},
139+
{
140+
colorMode: terminalapi.ColorMode216,
141+
opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
142+
want: tcell.StyleDefault.Foreground(tcell.Color23).Background(tcell.Color16),
143+
},
144+
}
145+
146+
for _, tc := range tests {
147+
t.Run(tc.opts.FgColor.String()+"+"+tc.opts.BgColor.String(), func(t *testing.T) {
148+
got := cellOptsToStyle(&tc.opts, tc.colorMode)
149+
if got != tc.want {
150+
fg, bg, _ := got.Decompose()
151+
wantFg, wantBg, _ := tc.want.Decompose()
152+
t.Errorf("cellOptsToStyle(%v, fg=%v, bg=%v) => got (fg=%X, bg=%X), want (fg=%X, bg=%X)",
153+
tc.colorMode, tc.opts.FgColor, tc.opts.BgColor, fg, bg, wantFg, wantBg)
154+
}
155+
})
156+
}
157+
}

0 commit comments

Comments
 (0)