Projects STRLCPY termdash Commits fbd21e79
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    .travis.yml
    skipped 2 lines
    3 3   - 1.14.x
    4 4   - 1.15.x
    5 5   - stable
     6 +before_install:
     7 + - go get github.com/mattn/goveralls
    6 8  script:
    7 9   - go get -t ./...
    8 10   - go get -u golang.org/x/lint/golint
    skipped 3 lines
    12 14   - diff -u <(echo -n) <(gofmt -d -s .)
    13 15   - diff -u <(echo -n) <(./internal/scripts/autogen_licences.sh .)
    14 16   - diff -u <(echo -n) <(golint ./...)
     17 + - $GOPATH/bin/goveralls -service=travis-pro
    15 18  env:
    16 19   global:
    17 20   - CGO_ENABLED=0
     21 + - secure: VOOh/w2YNAn+psiWYjIOQ5ZhhMb6Wz7zzmhIlj0dc5mGQztFAX5TuNWOU5JokvOigFy18JhPeDJRmp661xqM4gy1Znx1odSXES3YdCwt42pmpjYIkI9lI09xTRH6WYIRmYfCHe4J3A9/CWLeDRaAU1e+YqmNyraaGzE82ouUPH/I4A9gur4j4j6t1X/t0iovyd/4qNDsetUPevQsJS224Pv6Xhg3LGnSAXMPM+tu0t3UeEfRu/l9OgP6/bnet9BUx0BryFCVJp6fAtq7x61+WRIJesugrhHVgl/dz8CgFsVjRkqWQSNnZvt07dHNOX0mZj2U22OAkH+9ZN93wScs3bDZFXozrta7eOWhrJLcJTMrAxdHYMNKmoXqQQ0TGFV/L9blOtT8uj9US3wxeD11s4TyZePWIC5hnpUsNFoGPsBB45uwW2TSwvTTEL9bxWWzjYzSkLG5P6Kk4/JkeMh3OMFCM/LutX8QDch1n/s0CfXdy7qgh5G4I9ZhGTU+huJlumeuM4U+my0EPnA3uclJ97cw0n6K7MKwKCTTA8La2ifATunKC/U4Hjo1rf9DxofIrRIvwV5zEUIn1r6ut5fO+o+MWDupkvsMqIA7QJyCLhRp+pAlPWGDZLdrFEicN/kpULH4IGUIPn532gXzEOAG+Aq0WYDVPXGLSifSyxafiDk=
    18 22   
  • ■ ■ ■ ■ ■ ■
    CHANGELOG.md
    skipped 6 lines
    7 7   
    8 8  ## [Unreleased]
    9 9   
     10 +## [0.13.0] - 17-Nov-2020
     11 + 
     12 +### Added
     13 + 
     14 +- the `Text` widget now allows user to specify custom scroll marker runes.
     15 + 
     16 +### Changed
     17 + 
     18 +- terminal cells now support font modifier options (bold, italic,
     19 + underline, strike through).
     20 +- `tcell` dependency was upgraded to v2.0.0.
     21 +- upgraded versions of all other dependencies.
     22 +- aligned the definition of the first 16 colors with the definition used by
     23 + Xterm and `tcell`. Defined two non-standard colors `ColorMagenta` and
     24 + `ColorCyan` to make this change backward compatible for users that use
     25 + `termbox-go`.
     26 +- made `tcell` terminal implementation the default in examples, demos and
     27 + documentation.
     28 + 
     29 +### Fixed
     30 + 
     31 +- coveralls again triggers and reports on PRs.
     32 +- addressed some lint issues.
     33 +- improved test coverage in some modules.
     34 +- changed the Blue color in demos to a more visible shade.
     35 +- fixed a bug where segment display text in `termdashdemo` appeared to be
     36 + jumping.
     37 + 
    10 38  ## [0.12.2] - 31-Aug-2020
    11 39   
    12 40  ### Fixed
    skipped 328 lines
    341 369  - The Gauge widget.
    342 370  - The Text widget.
    343 371   
    344  -[unreleased]: https://github.com/mum4k/termdash/compare/v0.12.2...devel
     372 +[unreleased]: https://github.com/mum4k/termdash/compare/v0.13.0...devel
     373 +[0.13.0]: https://github.com/mum4k/termdash/compare/v0.12.2...v0.13.0
    345 374  [0.12.2]: https://github.com/mum4k/termdash/compare/v0.12.1...v0.12.2
    346 375  [0.12.1]: https://github.com/mum4k/termdash/compare/v0.12.0...v0.12.1
    347 376  [0.12.0]: https://github.com/mum4k/termdash/compare/v0.11.0...v0.12.0
    skipped 15 lines
  • ■ ■ ■ ■ ■ ■
    cell/cell.go
    skipped 22 lines
    23 23   
    24 24  // Options stores the provided options.
    25 25  type Options struct {
    26  - FgColor Color
    27  - BgColor Color
     26 + FgColor Color
     27 + BgColor Color
     28 + Bold bool
     29 + Italic bool
     30 + Underline bool
     31 + Strikethrough bool
     32 + Inverse bool
     33 + Blink bool
    28 34  }
    29 35   
    30 36  // Set allows existing options to be passed as an option.
    skipped 32 lines
    63 69   })
    64 70  }
    65 71   
     72 +// Bold makes cell's text bold.
     73 +func Bold() Option {
     74 + return option(func(co *Options) {
     75 + co.Bold = true
     76 + })
     77 +}
     78 + 
     79 +// Italic makes cell's text italic. Only works when using the tcell backend.
     80 +func Italic() Option {
     81 + return option(func(co *Options) {
     82 + co.Italic = true
     83 + })
     84 +}
     85 + 
     86 +// Underline makes cell's text underlined.
     87 +func Underline() Option {
     88 + return option(func(co *Options) {
     89 + co.Underline = true
     90 + })
     91 +}
     92 + 
     93 +// Strikethrough strikes through the cell's text. Only works when using the tcell backend.
     94 +func Strikethrough() Option {
     95 + return option(func(co *Options) {
     96 + co.Strikethrough = true
     97 + })
     98 +}
     99 + 
     100 +// Inverse inverts the colors of the cell's text.
     101 +func Inverse() Option {
     102 + return option(func(co *Options) {
     103 + co.Inverse = true
     104 + })
     105 +}
     106 + 
     107 +// Blink makes the cell's text blink. Only works when using the tcell backend.
     108 +func Blink() Option {
     109 + return option(func(co *Options) {
     110 + co.Blink = true
     111 + })
     112 +}
     113 + 
  • ■ ■ ■ ■ ■ ■
    cell/cell_test.go
    skipped 26 lines
    27 27   want *Options
    28 28   }{
    29 29   {
     30 + 
    30 31   desc: "no provided options",
    31 32   want: &Options{},
    32 33   },
    skipped 37 lines
    70 71   want: &Options{
    71 72   FgColor: ColorCyan,
    72 73   BgColor: ColorMagenta,
     74 + },
     75 + },
     76 + {
     77 + desc: "setting font attributes",
     78 + opts: []Option{
     79 + Bold(),
     80 + Italic(),
     81 + Underline(),
     82 + Strikethrough(),
     83 + Inverse(),
     84 + Blink(),
     85 + },
     86 + want: &Options{
     87 + Bold: true,
     88 + Italic: true,
     89 + Underline: true,
     90 + Strikethrough: true,
     91 + Inverse: true,
     92 + Blink: true,
    73 93   },
    74 94   },
    75 95   }
    skipped 11 lines
  • ■ ■ ■ ■ ■
    cell/color.go
    skipped 47 lines
    48 48  const (
    49 49   ColorDefault Color = iota
    50 50   
    51  - // 8 "system" colors.
     51 + // The 16 Xterm colors.
     52 + // See https://jonasjacek.github.io/colors/
    52 53   ColorBlack
     54 + ColorMaroon
     55 + ColorGreen
     56 + ColorOlive
     57 + ColorNavy
     58 + ColorPurple
     59 + ColorTeal
     60 + ColorSilver
     61 + ColorGray
    53 62   ColorRed
    54  - ColorGreen
     63 + ColorLime
    55 64   ColorYellow
    56 65   ColorBlue
    57  - ColorMagenta
    58  - ColorCyan
     66 + ColorFuchsia
     67 + ColorAqua
    59 68   ColorWhite
     69 +)
     70 + 
     71 +// Colors defined for backward compatibility with termbox-go.
     72 +const (
     73 + ColorMagenta Color = ColorPurple
     74 + ColorCyan Color = ColorTeal
    60 75  )
    61 76   
    62 77  // ColorNumber sets a color using its number.
    skipped 23 lines
    86 101   return ColorDefault
    87 102   }
    88 103   }
     104 + // Explanation:
     105 + // https://stackoverflow.com/questions/27159322/rgb-values-of-the-colors-in-the-ansi-extended-colors-index-17-255
    89 106   return Color(0x10 + 36*r + 6*g + b + 1) // Colors are off-by-one due to ColorDefault being zero.
    90 107  }
    91 108   
    skipped 16 lines
  • ■ ■ ■ ■ ■ ■
    container/grid/grid_test.go
    skipped 29 lines
    30 30   "github.com/mum4k/termdash/private/draw/testdraw"
    31 31   "github.com/mum4k/termdash/private/faketerm"
    32 32   "github.com/mum4k/termdash/private/fakewidget"
    33  - "github.com/mum4k/termdash/terminal/termbox"
     33 + "github.com/mum4k/termdash/terminal/tcell"
    34 34   "github.com/mum4k/termdash/widgetapi"
    35 35   "github.com/mum4k/termdash/widgets/barchart"
    36 36  )
    skipped 1 lines
    38 38  // Shows how to create a simple 4x4 grid with four widgets.
    39 39  // All the cells in the grid contain the same widget in this example.
    40 40  func Example() {
    41  - tbx, err := termbox.New()
     41 + t, err := tcell.New()
    42 42   if err != nil {
    43 43   panic(err)
    44 44   }
    45  - defer tbx.Close()
     45 + defer t.Close()
    46 46   
    47 47   bc, err := barchart.New()
    48 48   if err != nil {
    skipped 18 lines
    67 67   panic(err)
    68 68   }
    69 69   
    70  - cont, err := container.New(tbx, gridOpts...)
     70 + cont, err := container.New(t, gridOpts...)
    71 71   if err != nil {
    72 72   panic(err)
    73 73   }
    74 74   
    75 75   ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    76 76   defer cancel()
    77  - if err := termdash.Run(ctx, tbx, cont); err != nil {
     77 + if err := termdash.Run(ctx, t, cont); err != nil {
    78 78   panic(err)
    79 79   }
    80 80  }
    skipped 1 lines
    82 82  // Shows how to create rows iteratively. Each row contains two columns and each
    83 83  // column contains the same widget.
    84 84  func Example_iterative() {
    85  - tbx, err := termbox.New()
     85 + t, err := tcell.New()
    86 86   if err != nil {
    87 87   panic(err)
    88 88   }
    89  - defer tbx.Close()
     89 + defer t.Close()
    90 90   
    91 91   bc, err := barchart.New()
    92 92   if err != nil {
    skipped 15 lines
    108 108   panic(err)
    109 109   }
    110 110   
    111  - cont, err := container.New(tbx, gridOpts...)
     111 + cont, err := container.New(t, gridOpts...)
    112 112   if err != nil {
    113 113   panic(err)
    114 114   }
    115 115   
    116 116   ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    117 117   defer cancel()
    118  - if err := termdash.Run(ctx, tbx, cont); err != nil {
     118 + if err := termdash.Run(ctx, t, cont); err != nil {
    119 119   panic(err)
    120 120   }
    121 121  }
    skipped 950 lines
  • ■ ■ ■ ■ ■ ■
    go.mod
    skipped 2 lines
    3 3  go 1.14
    4 4   
    5 5  require (
    6  - github.com/gdamore/tcell v1.3.0
     6 + github.com/gdamore/tcell/v2 v2.0.0
    7 7   github.com/kylelemons/godebug v1.1.0
    8 8   github.com/mattn/go-runewidth v0.0.9
    9  - github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be
     9 + github.com/nsf/termbox-go v0.0.0-20201107200903-9b52a5faed9e
     10 + golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba // indirect
     11 + golang.org/x/text v0.3.4 // indirect
    10 12  )
    11 13   
  • ■ ■ ■ ■ ■ ■
    go.sum
    skipped 3 lines
    4 4  github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
    5 5  github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
    6 6  github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
     7 +github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
     8 +github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
     9 +github.com/gdamore/tcell/v2 v2.0.0 h1:GRWG8aLfWAlekj9Q6W29bVvkHENc6hp79XOqG4AWDOs=
     10 +github.com/gdamore/tcell/v2 v2.0.0/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
    7 11  github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
    8 12  github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
    9 13  github.com/lucasb-eyer/go-colorful v1.0.2 h1:mCMFu6PgSozg9tDNMMK3g18oJBX7oYGrC09mS6CXfO4=
    10 14  github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
     15 +github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
     16 +github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
    11 17  github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
     18 +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
    12 19  github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
    13 20  github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
    14 21  github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be h1:yzmWtPyxEUIKdZg4RcPq64MfS8NA6A5fNOJgYhpR9EQ=
    15 22  github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
     23 +github.com/nsf/termbox-go v0.0.0-20201107200903-9b52a5faed9e h1:T8/SzSWIDoWV9trslLNfUdJ5yHrIXXuODEy5M0vou4U=
     24 +github.com/nsf/termbox-go v0.0.0-20201107200903-9b52a5faed9e/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ=
    16 25  golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
    17 26  golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     27 +golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba h1:xmhUJGQGbxlod18iJGqVEp9cHIPLl7QiX2aA3to708s=
     28 +golang.org/x/sys v0.0.0-20201113233024-12cec1faf1ba/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    18 29  golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
    19 30  golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
     31 +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
     32 +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
     33 +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
    20 34   
  • ■ ■ ■ ■ ■ ■
    private/faketerm/diff_test.go
     1 +package faketerm
     2 + 
     3 +import (
     4 + "image"
     5 + "testing"
     6 + 
     7 + "github.com/mum4k/termdash/cell"
     8 +)
     9 + 
     10 +func TestDiff(t *testing.T) {
     11 + tests := []struct {
     12 + desc string
     13 + term1 *Terminal
     14 + term2 *Terminal
     15 + wantDiff bool
     16 + }{
     17 + {
     18 + desc: "no diff on equal terminals",
     19 + term1: func() *Terminal {
     20 + t := MustNew(image.Point{2, 2})
     21 + t.SetCell(image.Point{0, 0}, 'a')
     22 + return t
     23 + }(),
     24 + term2: func() *Terminal {
     25 + t := MustNew(image.Point{2, 2})
     26 + t.SetCell(image.Point{0, 0}, 'a')
     27 + return t
     28 + }(),
     29 + wantDiff: false,
     30 + },
     31 + {
     32 + desc: "reports diff on when cell runes differ",
     33 + term1: func() *Terminal {
     34 + t := MustNew(image.Point{2, 2})
     35 + t.SetCell(image.Point{0, 0}, 'a')
     36 + return t
     37 + }(),
     38 + term2: func() *Terminal {
     39 + t := MustNew(image.Point{2, 2})
     40 + t.SetCell(image.Point{1, 1}, 'a')
     41 + return t
     42 + }(),
     43 + wantDiff: true,
     44 + },
     45 + {
     46 + desc: "reports diff on when cell options differ",
     47 + term1: func() *Terminal {
     48 + t := MustNew(image.Point{2, 2})
     49 + t.SetCell(image.Point{0, 0}, 'a', cell.Bold())
     50 + return t
     51 + }(),
     52 + term2: func() *Terminal {
     53 + t := MustNew(image.Point{2, 2})
     54 + t.SetCell(image.Point{0, 0}, 'a')
     55 + return t
     56 + }(),
     57 + wantDiff: true,
     58 + },
     59 + }
     60 + 
     61 + for _, tc := range tests {
     62 + t.Run(tc.desc, func(t *testing.T) {
     63 + gotDiff := Diff(tc.term1, tc.term2)
     64 + if (gotDiff != "") != tc.wantDiff {
     65 + t.Errorf("Diff -> unexpected diff while wantDiff:%v, the diff:\n%s", tc.wantDiff, gotDiff)
     66 + }
     67 + })
     68 + }
     69 +}
     70 + 
  • ■ ■ ■ ■ ■ ■
    termdash_test.go
    skipped 31 lines
    32 32   "github.com/mum4k/termdash/private/event/testevent"
    33 33   "github.com/mum4k/termdash/private/faketerm"
    34 34   "github.com/mum4k/termdash/private/fakewidget"
    35  - "github.com/mum4k/termdash/terminal/termbox"
     35 + "github.com/mum4k/termdash/terminal/tcell"
    36 36   "github.com/mum4k/termdash/terminal/terminalapi"
    37 37   "github.com/mum4k/termdash/widgetapi"
    38 38   "github.com/mum4k/termdash/widgets/barchart"
    skipped 3 lines
    42 42  // Example shows how to setup and run termdash with periodic redraw.
    43 43  func Example() {
    44 44   // Create the terminal.
    45  - t, err := termbox.New()
     45 + t, err := tcell.New()
    46 46   if err != nil {
    47 47   panic(err)
    48 48   }
    skipped 37 lines
    86 86  // Example shows how to setup and run termdash with manually triggered redraw.
    87 87  func Example_triggered() {
    88 88   // Create the terminal.
    89  - t, err := termbox.New()
     89 + t, err := tcell.New()
    90 90   if err != nil {
    91 91   panic(err)
    92 92   }
    skipped 572 lines
  • ■ ■ ■ ■ ■ ■
    termdashdemo/termdashdemo.go
    skipped 19 lines
    20 20   "context"
    21 21   "flag"
    22 22   "fmt"
     23 + "image"
    23 24   "log"
    24 25   "math"
    25 26   "math/rand"
    skipped 43 lines
    69 70  }
    70 71   
    71 72  // newWidgets creates all widgets used by this demo.
    72  -func newWidgets(ctx context.Context, c *container.Container) (*widgets, error) {
     73 +func newWidgets(ctx context.Context, t terminalapi.Terminal, c *container.Container) (*widgets, error) {
    73 74   updateText := make(chan string)
    74  - sd, err := newSegmentDisplay(ctx, updateText)
     75 + sd, err := newSegmentDisplay(ctx, t, updateText)
    75 76   if err != nil {
    76 77   return nil, err
    77 78   }
    skipped 399 lines
    477 478   
    478 479  func main() {
    479 480   terminalPtr := flag.String("terminal",
    480  - "termbox",
    481  - "The terminal implementation to use. Available implementations are 'termbox' and 'tcell' (default = termbox).")
     481 + "tcell",
     482 + "The terminal implementation to use. Available implementations are 'termbox' and 'tcell' (default = tcell).")
    482 483   flag.Parse()
    483 484   
    484 485   var t terminalapi.Terminal
    skipped 19 lines
    504 505   }
    505 506   
    506 507   ctx, cancel := context.WithCancel(context.Background())
    507  - w, err := newWidgets(ctx, c)
     508 + w, err := newWidgets(ctx, t, c)
    508 509   if err != nil {
    509 510   panic(err)
    510 511   }
    skipped 58 lines
    569 570  // SegmentDisplay.
    570 571  func newTextInput(updateText chan<- string) (*textinput.TextInput, error) {
    571 572   input, err := textinput.New(
    572  - textinput.Label("Change text to: ", cell.FgColor(cell.ColorBlue)),
     573 + textinput.Label("Change text to: ", cell.FgColor(cell.ColorNumber(33))),
    573 574   textinput.MaxWidthCells(20),
    574 575   textinput.PlaceHolder("enter any text"),
    575 576   textinput.OnSubmit(func(text string) error {
    skipped 10 lines
    586 587   
    587 588  // newSegmentDisplay creates a new SegmentDisplay that initially shows the
    588 589  // Termdash name. Shows any text that is sent over the channel.
    589  -func newSegmentDisplay(ctx context.Context, updateText <-chan string) (*segmentdisplay.SegmentDisplay, error) {
     590 +func newSegmentDisplay(ctx context.Context, t terminalapi.Terminal, updateText <-chan string) (*segmentdisplay.SegmentDisplay, error) {
    590 591   sd, err := segmentdisplay.New()
    591 592   if err != nil {
    592 593   return nil, err
    593 594   }
    594 595   
    595 596   colors := []cell.Color{
    596  - cell.ColorBlue,
     597 + cell.ColorNumber(33),
    597 598   cell.ColorRed,
    598 599   cell.ColorYellow,
    599  - cell.ColorBlue,
     600 + cell.ColorNumber(33),
    600 601   cell.ColorGreen,
    601 602   cell.ColorRed,
    602 603   cell.ColorGreen,
    skipped 6 lines
    609 610   go func() {
    610 611   ticker := time.NewTicker(500 * time.Millisecond)
    611 612   defer ticker.Stop()
     613 + 
     614 + capacity := 0
     615 + termSize := t.Size()
    612 616   for {
    613 617   select {
    614 618   case <-ticker.C:
    615  - state := textState(text, sd.Capacity(), step)
     619 + if capacity == 0 {
     620 + // The segment display only knows its capacity after both
     621 + // text size and terminal size are known.
     622 + capacity = sd.Capacity()
     623 + }
     624 + if t.Size().Eq(image.ZP) || !t.Size().Eq(termSize) {
     625 + // Update the capacity initially the first time the
     626 + // terminal reports a non-zero size and then every time the
     627 + // terminal resizes.
     628 + //
     629 + // This is better than updating the capacity on every
     630 + // iteration since that leads to edge cases - segment
     631 + // display capacity depends on the length of text and here
     632 + // we are trying to adjust the text length to the capacity.
     633 + termSize = t.Size()
     634 + capacity = sd.Capacity()
     635 + }
     636 + 
     637 + state := textState(text, capacity, step)
    616 638   var chunks []*segmentdisplay.TextChunk
    617  - for i := 0; i < sd.Capacity(); i++ {
     639 + for i := 0; i < capacity; i++ {
    618 640   if i >= len(state) {
    619 641   break
    620 642   }
    skipped 233 lines
    854 876   go periodic(ctx, redrawInterval/3, func() error {
    855 877   step1 = (step1 + 1) % len(inputs)
    856 878   if err := lc.Series("first", rotateFloats(inputs, step1),
    857  - linechart.SeriesCellOpts(cell.FgColor(cell.ColorBlue)),
     879 + linechart.SeriesCellOpts(cell.FgColor(cell.ColorNumber(33))),
    858 880   ); err != nil {
    859 881   return err
    860 882   }
    skipped 112 lines
  • ■ ■ ■ ■ ■ ■
    terminal/tcell/cell_options.go
    skipped 14 lines
    15 15  package tcell
    16 16   
    17 17  import (
    18  - "github.com/gdamore/tcell"
     18 + tcell "github.com/gdamore/tcell/v2"
    19 19   "github.com/mum4k/termdash/cell"
    20 20   "github.com/mum4k/termdash/terminal/terminalapi"
    21 21  )
    22 22   
    23 23  // cellColor converts termdash cell color to the tcell format.
    24 24  func cellColor(c cell.Color) tcell.Color {
    25  - return tcell.Color(c&0x1ff) - 1
     25 + if c == cell.ColorDefault {
     26 + return tcell.ColorDefault
     27 + }
     28 + // Subtract one, because cell.ColorBlack has value one instead of zero.
     29 + // Zero is used for cell.ColorDefault instead.
     30 + return tcell.Color(c-1) + tcell.ColorValid
    26 31  }
    27 32   
    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 {
     33 +// colorToMode adjusts the color to the color mode.
     34 +func colorToMode(c cell.Color, colorMode terminalapi.ColorMode) cell.Color {
     35 + if c == cell.ColorDefault {
    31 36   return c
    32 37   }
    33 38   switch colorMode {
    34 39   case terminalapi.ColorModeNormal:
    35  - c %= tcell.Color(16)
     40 + c %= 16 + 1 // Add one for cell.ColorDefault.
    36 41   case terminalapi.ColorMode256:
    37  - c %= tcell.Color(256)
     42 + c %= 256 + 1 // Add one for cell.ColorDefault.
    38 43   case terminalapi.ColorMode216:
    39  - c %= tcell.Color(216)
    40  - c += tcell.Color(16)
     44 + if c <= 216 { // Add one for cell.ColorDefault.
     45 + return c + 16
     46 + }
     47 + c = c%216 + 16
    41 48   case terminalapi.ColorModeGrayscale:
    42  - c %= tcell.Color(24)
    43  - c += tcell.Color(232)
     49 + if c <= 24 { // Add one for cell.ColorDefault.
     50 + return c + 232
     51 + }
     52 + c = c%24 + 232
    44 53   default:
    45  - c = tcell.ColorDefault
     54 + c = cell.ColorDefault
    46 55   }
    47 56   return c
    48 57  }
    skipped 2 lines
    51 60  func cellOptsToStyle(opts *cell.Options, colorMode terminalapi.ColorMode) tcell.Style {
    52 61   st := tcell.StyleDefault
    53 62   
    54  - fg := cellColor(opts.FgColor)
    55  - bg := cellColor(opts.BgColor)
    56  - 
    57  - fg = fixColor(fg, colorMode)
    58  - bg = fixColor(bg, colorMode)
     63 + fg := cellColor(colorToMode(opts.FgColor, colorMode))
     64 + bg := cellColor(colorToMode(opts.BgColor, colorMode))
    59 65   
    60  - st = st.Foreground(fg).Background(bg)
     66 + st = st.Foreground(fg).
     67 + Background(bg).
     68 + Bold(opts.Bold).
     69 + Italic(opts.Italic).
     70 + Underline(opts.Underline).
     71 + StrikeThrough(opts.Strikethrough).
     72 + Reverse(opts.Inverse).
     73 + Blink(opts.Blink)
    61 74   return st
    62 75  }
    63 76   
  • ■ ■ ■ ■ ■ ■
    terminal/tcell/cell_options_test.go
    skipped 14 lines
    15 15  package tcell
    16 16   
    17 17  import (
     18 + "reflect"
    18 19   "testing"
    19 20   
    20  - "github.com/gdamore/tcell"
     21 + tcell "github.com/gdamore/tcell/v2"
     22 + "github.com/kylelemons/godebug/pretty"
    21 23   "github.com/mum4k/termdash/cell"
    22 24   "github.com/mum4k/termdash/terminal/terminalapi"
    23 25  )
    24 26   
    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 27  func TestCellOptsToStyle(t *testing.T) {
    119 28   tests := []struct {
     29 + desc string
    120 30   colorMode terminalapi.ColorMode
    121 31   opts cell.Options
    122 32   want tcell.Style
    123 33   }{
    124 34   {
     35 + desc: "ColorMode256: ColorDefault and ColorBlack",
    125 36   colorMode: terminalapi.ColorMode256,
    126  - opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
    127  - want: tcell.StyleDefault.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
     37 + opts: cell.Options{
     38 + FgColor: cell.ColorDefault,
     39 + BgColor: cell.ColorBlack,
     40 + },
     41 + want: tcell.StyleDefault.
     42 + Foreground(tcell.ColorDefault).
     43 + Background(tcell.ColorBlack),
     44 + },
     45 + {
     46 + desc: "ColorMode256: ColorMaroon and ColorGreen",
     47 + colorMode: terminalapi.ColorMode256,
     48 + opts: cell.Options{
     49 + FgColor: cell.ColorMaroon,
     50 + BgColor: cell.ColorGreen,
     51 + },
     52 + want: tcell.StyleDefault.
     53 + Foreground(tcell.ColorMaroon).
     54 + Background(tcell.ColorGreen),
     55 + },
     56 + {
     57 + desc: "ColorMode256: ColorOlive and ColorNavy",
     58 + colorMode: terminalapi.ColorMode256,
     59 + opts: cell.Options{
     60 + FgColor: cell.ColorOlive,
     61 + BgColor: cell.ColorNavy,
     62 + },
     63 + want: tcell.StyleDefault.
     64 + Foreground(tcell.ColorOlive).
     65 + Background(tcell.ColorNavy),
     66 + },
     67 + {
     68 + desc: "ColorMode256: ColorPurple and ColorTeal",
     69 + colorMode: terminalapi.ColorMode256,
     70 + opts: cell.Options{
     71 + FgColor: cell.ColorPurple,
     72 + BgColor: cell.ColorTeal,
     73 + },
     74 + want: tcell.StyleDefault.
     75 + Foreground(tcell.ColorPurple).
     76 + Background(tcell.ColorTeal),
     77 + },
     78 + {
     79 + desc: "ColorMode256: ColorSilver and ColorGray",
     80 + colorMode: terminalapi.ColorMode256,
     81 + opts: cell.Options{
     82 + FgColor: cell.ColorSilver,
     83 + BgColor: cell.ColorGray,
     84 + },
     85 + want: tcell.StyleDefault.
     86 + Foreground(tcell.ColorSilver).
     87 + Background(tcell.ColorGray),
     88 + },
     89 + {
     90 + desc: "ColorMode256: ColorRed and ColorLime",
     91 + colorMode: terminalapi.ColorMode256,
     92 + opts: cell.Options{
     93 + FgColor: cell.ColorRed,
     94 + BgColor: cell.ColorLime,
     95 + },
     96 + want: tcell.StyleDefault.
     97 + Foreground(tcell.ColorRed).
     98 + Background(tcell.ColorLime),
     99 + },
     100 + {
     101 + desc: "ColorMode256: ColorYellow and ColorBlue",
     102 + colorMode: terminalapi.ColorMode256,
     103 + opts: cell.Options{
     104 + FgColor: cell.ColorYellow,
     105 + BgColor: cell.ColorBlue,
     106 + },
     107 + want: tcell.StyleDefault.
     108 + Foreground(tcell.ColorYellow).
     109 + Background(tcell.ColorBlue),
     110 + },
     111 + {
     112 + desc: "ColorMode256: ColorFuchsia and ColorAqua",
     113 + colorMode: terminalapi.ColorMode256,
     114 + opts: cell.Options{
     115 + FgColor: cell.ColorFuchsia,
     116 + BgColor: cell.ColorAqua,
     117 + },
     118 + want: tcell.StyleDefault.
     119 + Foreground(tcell.ColorFuchsia).
     120 + Background(tcell.ColorAqua),
     121 + },
     122 + {
     123 + desc: "ColorMode256: ColorWhite and ColorDefault",
     124 + colorMode: terminalapi.ColorMode256,
     125 + opts: cell.Options{
     126 + FgColor: cell.ColorWhite,
     127 + BgColor: cell.ColorDefault,
     128 + },
     129 + want: tcell.StyleDefault.
     130 + Foreground(tcell.ColorWhite).
     131 + Background(tcell.ColorDefault),
     132 + },
     133 + {
     134 + desc: "ColorMode256: termbox compatibility colors ColorMagenta and ColorCyan",
     135 + colorMode: terminalapi.ColorMode256,
     136 + opts: cell.Options{
     137 + FgColor: cell.ColorMagenta,
     138 + BgColor: cell.ColorCyan,
     139 + },
     140 + want: tcell.StyleDefault.
     141 + Foreground(tcell.ColorPurple).
     142 + Background(tcell.ColorTeal),
     143 + },
     144 + {
     145 + desc: "ColorMode256: first(0) and last(255) numbered color",
     146 + colorMode: terminalapi.ColorMode256,
     147 + opts: cell.Options{
     148 + FgColor: cell.ColorNumber(0),
     149 + BgColor: cell.ColorNumber(255),
     150 + },
     151 + want: tcell.StyleDefault.
     152 + Foreground(tcell.ColorBlack).
     153 + Background(tcell.Color255),
     154 + },
     155 + {
     156 + desc: "ColorMode256: two numbered colors",
     157 + colorMode: terminalapi.ColorMode256,
     158 + opts: cell.Options{
     159 + FgColor: cell.ColorNumber(33),
     160 + BgColor: cell.ColorNumber(200),
     161 + },
     162 + want: tcell.StyleDefault.
     163 + Foreground(tcell.Color33).
     164 + Background(tcell.Color200),
     165 + },
     166 + {
     167 + desc: "ColorMode256: first and last RGB6 color",
     168 + colorMode: terminalapi.ColorMode256,
     169 + opts: cell.Options{
     170 + FgColor: cell.ColorRGB6(0, 0, 0),
     171 + BgColor: cell.ColorRGB6(5, 5, 5),
     172 + },
     173 + want: tcell.StyleDefault.
     174 + Foreground(tcell.Color16).
     175 + Background(tcell.Color231),
     176 + },
     177 + {
     178 + desc: "ColorMode256: first and last RGB24 color",
     179 + colorMode: terminalapi.ColorMode256,
     180 + opts: cell.Options{
     181 + FgColor: cell.ColorRGB24(0, 0, 0),
     182 + BgColor: cell.ColorRGB24(255, 255, 255),
     183 + },
     184 + want: tcell.StyleDefault.
     185 + Foreground(tcell.Color16).
     186 + Background(tcell.Color231),
    128 187   },
    129 188   {
     189 + desc: "ColorModeNormal: first and last color",
    130 190   colorMode: terminalapi.ColorModeNormal,
    131  - opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
    132  - want: tcell.StyleDefault.Foreground(tcell.ColorSilver).Background(tcell.ColorBlack),
     191 + opts: cell.Options{
     192 + FgColor: cell.ColorBlack,
     193 + BgColor: cell.ColorWhite,
     194 + },
     195 + want: tcell.StyleDefault.
     196 + Foreground(tcell.ColorBlack).
     197 + Background(tcell.ColorWhite),
    133 198   },
    134 199   {
    135  - colorMode: terminalapi.ColorModeGrayscale,
    136  - opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
    137  - want: tcell.StyleDefault.Foreground(tcell.Color239).Background(tcell.Color232),
     200 + desc: "ColorModeNormal: colors in the middle",
     201 + colorMode: terminalapi.ColorModeNormal,
     202 + opts: cell.Options{
     203 + FgColor: cell.ColorGreen,
     204 + BgColor: cell.ColorOlive,
     205 + },
     206 + want: tcell.StyleDefault.
     207 + Foreground(tcell.ColorGreen).
     208 + Background(tcell.ColorOlive),
    138 209   },
    139 210   {
     211 + desc: "ColorModeNormal: colors above the range rotate back",
     212 + colorMode: terminalapi.ColorModeNormal,
     213 + opts: cell.Options{
     214 + FgColor: cell.ColorNumber(17),
     215 + BgColor: cell.ColorNumber(18),
     216 + },
     217 + want: tcell.StyleDefault.
     218 + Foreground(tcell.ColorBlack).
     219 + Background(tcell.ColorMaroon),
     220 + },
     221 + {
     222 + desc: "ColorMode216: first and last color",
    140 223   colorMode: terminalapi.ColorMode216,
    141  - opts: cell.Options{FgColor: cell.ColorWhite, BgColor: cell.ColorBlack},
    142  - want: tcell.StyleDefault.Foreground(tcell.Color23).Background(tcell.Color16),
     224 + opts: cell.Options{
     225 + FgColor: cell.ColorNumber(0),
     226 + BgColor: cell.ColorNumber(215),
     227 + },
     228 + want: tcell.StyleDefault.
     229 + Foreground(tcell.Color16).
     230 + Background(tcell.Color231),
     231 + },
     232 + {
     233 + desc: "ColorMode216: colors in the middle",
     234 + colorMode: terminalapi.ColorMode216,
     235 + opts: cell.Options{
     236 + FgColor: cell.ColorNumber(1),
     237 + BgColor: cell.ColorNumber(2),
     238 + },
     239 + want: tcell.StyleDefault.
     240 + Foreground(tcell.Color17).
     241 + Background(tcell.Color18),
     242 + },
     243 + {
     244 + desc: "ColorMode216: colors above the range rotate back",
     245 + colorMode: terminalapi.ColorMode216,
     246 + opts: cell.Options{
     247 + FgColor: cell.ColorNumber(216),
     248 + BgColor: cell.ColorNumber(217),
     249 + },
     250 + want: tcell.StyleDefault.
     251 + Foreground(tcell.Color16).
     252 + Background(tcell.Color17),
     253 + },
     254 + {
     255 + desc: "ColorModeGrayscale: first and last color",
     256 + colorMode: terminalapi.ColorModeGrayscale,
     257 + opts: cell.Options{
     258 + FgColor: cell.ColorNumber(0),
     259 + BgColor: cell.ColorNumber(23),
     260 + },
     261 + want: tcell.StyleDefault.
     262 + Foreground(tcell.Color232).
     263 + Background(tcell.Color255),
     264 + },
     265 + {
     266 + desc: "ColorModeGrayscale: colors in the middle",
     267 + colorMode: terminalapi.ColorModeGrayscale,
     268 + opts: cell.Options{
     269 + FgColor: cell.ColorNumber(1),
     270 + BgColor: cell.ColorNumber(2),
     271 + },
     272 + want: tcell.StyleDefault.
     273 + Foreground(tcell.Color233).
     274 + Background(tcell.Color234),
     275 + },
     276 + {
     277 + desc: "ColorModeGrayscale: colors above the range rotate back",
     278 + colorMode: terminalapi.ColorModeGrayscale,
     279 + opts: cell.Options{
     280 + FgColor: cell.ColorNumber(24),
     281 + BgColor: cell.ColorNumber(25),
     282 + },
     283 + want: tcell.StyleDefault.
     284 + Foreground(tcell.Color232).
     285 + Background(tcell.Color233),
     286 + },
     287 + {
     288 + desc: "Unknown color mode converts to default color",
     289 + colorMode: terminalapi.ColorMode(-1),
     290 + opts: cell.Options{
     291 + FgColor: cell.ColorNumber(24),
     292 + BgColor: cell.ColorNumber(25),
     293 + },
     294 + want: tcell.StyleDefault.
     295 + Foreground(tcell.ColorDefault).
     296 + Background(tcell.ColorDefault),
     297 + },
     298 + {
     299 + colorMode: terminalapi.ColorModeNormal,
     300 + opts: cell.Options{Bold: true},
     301 + want: tcell.StyleDefault.Bold(true),
     302 + },
     303 + {
     304 + colorMode: terminalapi.ColorModeNormal,
     305 + opts: cell.Options{Italic: true},
     306 + want: tcell.StyleDefault.Italic(true),
     307 + },
     308 + {
     309 + colorMode: terminalapi.ColorModeNormal,
     310 + opts: cell.Options{Underline: true},
     311 + want: tcell.StyleDefault.Underline(true),
     312 + },
     313 + {
     314 + colorMode: terminalapi.ColorModeNormal,
     315 + opts: cell.Options{Strikethrough: true},
     316 + want: tcell.StyleDefault.StrikeThrough(true),
     317 + },
     318 + {
     319 + colorMode: terminalapi.ColorModeNormal,
     320 + opts: cell.Options{Inverse: true},
     321 + want: tcell.StyleDefault.Reverse(true),
     322 + },
     323 + {
     324 + colorMode: terminalapi.ColorModeNormal,
     325 + opts: cell.Options{Blink: true},
     326 + want: tcell.StyleDefault.Blink(true),
    143 327   },
    144 328   }
    145 329   
    146 330   for _, tc := range tests {
    147  - t.Run(tc.opts.FgColor.String()+"+"+tc.opts.BgColor.String(), func(t *testing.T) {
     331 + t.Run(tc.desc, func(t *testing.T) {
    148 332   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)
     333 + if !reflect.DeepEqual(got, tc.want) {
     334 + diff := pretty.Compare(tc.want, got)
     335 + t.Logf("opts: %+v\nstyle:%+v", tc.opts, got)
     336 + t.Errorf("cellOptsToStyle => unexpected diff (-want, +got):\n%s", diff)
    154 337   }
    155 338   })
    156 339   }
    skipped 2 lines
  • ■ ■ ■ ■ ■
    terminal/tcell/event.go
    skipped 16 lines
    17 17  import (
    18 18   "image"
    19 19   
    20  - "github.com/gdamore/tcell"
     20 + tcell "github.com/gdamore/tcell/v2"
    21 21   "github.com/mum4k/termdash/keyboard"
    22 22   "github.com/mum4k/termdash/mouse"
    23 23   "github.com/mum4k/termdash/terminal/terminalapi"
    skipped 111 lines
    135 135   }
    136 136   }
    137 137   
    138  - // Get only button events, not wheel events
    139  - tcellBtn &= tcell.ButtonMask(0xff)
    140 138   switch tcellBtn = event.Buttons(); tcellBtn {
    141 139   case tcell.ButtonNone:
    142 140   button = mouse.ButtonRelease
    skipped 58 lines
  • ■ ■ ■ ■
    terminal/tcell/event_test.go
    skipped 20 lines
    21 21   "testing"
    22 22   "time"
    23 23   
    24  - "github.com/gdamore/tcell"
     24 + tcell "github.com/gdamore/tcell/v2"
    25 25   "github.com/kylelemons/godebug/pretty"
    26 26   "github.com/mum4k/termdash/keyboard"
    27 27   "github.com/mum4k/termdash/mouse"
    skipped 255 lines
  • ■ ■ ■ ■ ■ ■
    terminal/tcell/tcell.go
    skipped 18 lines
    19 19   "fmt"
    20 20   "image"
    21 21   
    22  - "github.com/gdamore/tcell"
    23  - "github.com/gdamore/tcell/encoding"
     22 + tcell "github.com/gdamore/tcell/v2"
     23 + "github.com/gdamore/tcell/v2/encoding"
    24 24   "github.com/mum4k/termdash/cell"
    25 25   "github.com/mum4k/termdash/private/event/eventqueue"
    26 26   "github.com/mum4k/termdash/terminal/terminalapi"
    skipped 179 lines
  • ■ ■ ■ ■
    terminal/tcell/tcell_test.go
    skipped 16 lines
    17 17  import (
    18 18   "testing"
    19 19   
    20  - "github.com/gdamore/tcell"
     20 + tcell "github.com/gdamore/tcell/v2"
    21 21   "github.com/kylelemons/godebug/pretty"
    22 22   "github.com/mum4k/termdash/cell"
    23 23   "github.com/mum4k/termdash/terminal/terminalapi"
    skipped 99 lines
  • ■ ■ ■ ■ ■ ■
    terminal/termbox/cell_options.go
    skipped 16 lines
    17 17  // cell_options.go converts termdash cell options to the termbox format.
    18 18   
    19 19  import (
     20 + "errors"
     21 + 
    20 22   "github.com/mum4k/termdash/cell"
    21 23   tbx "github.com/nsf/termbox-go"
    22 24  )
    23 25   
    24 26  // cellColor converts termdash cell color to the termbox format.
    25 27  func cellColor(c cell.Color) tbx.Attribute {
    26  - return tbx.Attribute(c)
     28 + // Special cases for backward compatibility after we have aligned the
     29 + // definition of the first 16 colors with Xterm and tcell.
     30 + // This ensures that users that run with termbox-go don't experience any
     31 + // change in colors.
     32 + switch c {
     33 + case cell.ColorRed:
     34 + return tbx.Attribute(cell.ColorMaroon)
     35 + case cell.ColorYellow:
     36 + return tbx.Attribute(cell.ColorOlive)
     37 + case cell.ColorBlue:
     38 + return tbx.Attribute(cell.ColorNavy)
     39 + case cell.ColorWhite:
     40 + return tbx.Attribute(cell.ColorSilver)
     41 + default:
     42 + return tbx.Attribute(c)
     43 + }
    27 44  }
    28 45   
    29 46  // cellOptsToFg converts the cell options to the termbox foreground attribute.
    30  -func cellOptsToFg(opts *cell.Options) tbx.Attribute {
    31  - return cellColor(opts.FgColor)
     47 +func cellOptsToFg(opts *cell.Options) (tbx.Attribute, error) {
     48 + a := cellColor(opts.FgColor)
     49 + if opts.Bold {
     50 + a |= tbx.AttrBold
     51 + }
     52 + // Termbox doesn't have an italics attribute
     53 + if opts.Italic {
     54 + return 0, errors.New("Termbox: Unsupported attribute: Italic")
     55 + }
     56 + if opts.Underline {
     57 + a |= tbx.AttrUnderline
     58 + }
     59 + // Termbox doesn't have a strikethrough attribute
     60 + if opts.Strikethrough {
     61 + return 0, errors.New("Termbox: Unsupported attribute: Strikethrough")
     62 + }
     63 + if opts.Inverse {
     64 + a |= tbx.AttrReverse
     65 + }
     66 + // Termbox doesn't have a blink attribute
     67 + if opts.Blink {
     68 + return 0, errors.New("Termbox: Unsupported attribute: Blink")
     69 + }
     70 + return a, nil
    32 71  }
    33 72   
    34 73  // cellOptsToBg converts the cell options to the termbox background attribute.
    skipped 4 lines
  • ■ ■ ■ ■ ■ ■
    terminal/termbox/cell_options_test.go
    skipped 14 lines
    15 15  package termbox
    16 16   
    17 17  import (
     18 + "fmt"
    18 19   "testing"
    19 20   
    20 21   "github.com/mum4k/termdash/cell"
    skipped 28 lines
    49 50   }
    50 51  }
    51 52   
     53 +func TestCellFontModifier(t *testing.T) {
     54 + tests := []struct {
     55 + opt cell.Options
     56 + want tbx.Attribute
     57 + wantErr bool
     58 + }{
     59 + {cell.Options{Bold: true}, tbx.AttrBold, false},
     60 + {cell.Options{Underline: true}, tbx.AttrUnderline, false},
     61 + {cell.Options{Italic: true}, 0, true},
     62 + {cell.Options{Strikethrough: true}, 0, true},
     63 + {cell.Options{Inverse: true}, tbx.AttrReverse, false},
     64 + {cell.Options{Blink: true}, 0, true},
     65 + }
     66 + 
     67 + for _, tc := range tests {
     68 + t.Run(fmt.Sprintf("%v", tc.opt), func(t *testing.T) {
     69 + got, err := cellOptsToFg(&tc.opt)
     70 + if (err != nil) != tc.wantErr {
     71 + t.Errorf("cellOptsToFg(%v) => unexpected error: %v, wantErr: %v", tc.opt, err, tc.wantErr)
     72 + }
     73 + if err != nil {
     74 + return
     75 + }
     76 + if got != tc.want {
     77 + t.Errorf("cellOptsToFg(%v) => got %v, want %v", tc.opt, got, tc.want)
     78 + }
     79 + })
     80 + }
     81 +}
     82 + 
  • ■ ■ ■ ■ ■
    terminal/termbox/termbox.go
    skipped 12 lines
    13 13  // limitations under the License.
    14 14   
    15 15  // Package termbox implements terminal using the nsf/termbox-go library.
     16 +// Prefer to use tcell instead, nsf/termbox-go is no longer maintained.
    16 17  package termbox
    17 18   
    18 19  import (
    skipped 33 lines
    52 53   
    53 54  // Terminal provides input and output to a real terminal. Wraps the
    54 55  // nsf/termbox-go terminal implementation. This object is not thread-safe.
     56 +//
     57 +// Prefer to use tcell instead, nsf/termbox-go is no longer maintained.
     58 +//
    55 59  // Implements terminalapi.Terminal.
    56 60  type Terminal struct {
    57 61   // events is a queue of input events.
    skipped 47 lines
    105 109  // Clear implements terminalapi.Terminal.Clear.
    106 110  func (t *Terminal) Clear(opts ...cell.Option) error {
    107 111   o := cell.NewOptions(opts...)
    108  - return tbx.Clear(cellOptsToFg(o), cellOptsToBg(o))
     112 + fg, err := cellOptsToFg(o)
     113 + if err != nil {
     114 + return err
     115 + }
     116 + return tbx.Clear(fg, cellOptsToBg(o))
    109 117  }
    110 118   
    111 119  // Flush implements terminalapi.Terminal.Flush.
    skipped 14 lines
    126 134  // SetCell implements terminalapi.Terminal.SetCell.
    127 135  func (t *Terminal) SetCell(p image.Point, r rune, opts ...cell.Option) error {
    128 136   o := cell.NewOptions(opts...)
    129  - tbx.SetCell(p.X, p.Y, r, cellOptsToFg(o), cellOptsToBg(o))
     137 + fg, err := cellOptsToFg(o)
     138 + if err != nil {
     139 + return err
     140 + }
     141 + tbx.SetCell(p.X, p.Y, r, fg, cellOptsToBg(o))
    130 142   return nil
    131 143  }
    132 144   
    skipped 33 lines
  • ■ ■ ■ ■ ■ ■
    terminal/terminalapi/color_mode.go
    skipped 36 lines
    37 37   
    38 38  // Supported color modes.
    39 39  const (
    40  - // ColorModeNormal supports 8 "system" colors.
     40 + // ColorModeNormal supports 16 Xterm colors.
    41 41   // These are defined as constants in the cell package.
    42 42   ColorModeNormal ColorMode = iota
    43 43   
    44 44   // ColorMode256 enables using any of the 256 terminal colors.
    45  - // 0-7: the 8 "system" colors accessible in ColorModeNormal.
    46  - // 8-15: the 8 "bright system" colors.
     45 + // 0-7: the 8 Xterm colors accessible in ColorModeNormal.
     46 + // 8-15: the 8 "bright" Xterm colors.
    47 47   // 16-231: the 216 different terminal colors.
    48 48   // 232-255: the 24 different shades of grey.
    49 49   ColorMode256
    skipped 12 lines
  • ■ ■ ■ ■ ■ ■
    widgets/barchart/barchartdemo/barchartdemo.go
    skipped 24 lines
    25 25   "github.com/mum4k/termdash/cell"
    26 26   "github.com/mum4k/termdash/container"
    27 27   "github.com/mum4k/termdash/linestyle"
    28  - "github.com/mum4k/termdash/terminal/termbox"
     28 + "github.com/mum4k/termdash/terminal/tcell"
    29 29   "github.com/mum4k/termdash/terminal/terminalapi"
    30 30   "github.com/mum4k/termdash/widgets/barchart"
    31 31  )
    skipped 24 lines
    56 56  }
    57 57   
    58 58  func main() {
    59  - t, err := termbox.New()
     59 + t, err := tcell.New()
    60 60   if err != nil {
    61 61   panic(err)
    62 62   }
    skipped 12 lines
    75 75   barchart.ValueColors([]cell.Color{
    76 76   cell.ColorRed,
    77 77   cell.ColorYellow,
    78  - cell.ColorBlue,
     78 + cell.ColorNumber(33),
    79 79   cell.ColorGreen,
    80 80   cell.ColorRed,
    81  - cell.ColorBlue,
     81 + cell.ColorNumber(33),
    82 82   }),
    83 83   barchart.ShowValues(),
    84 84   barchart.BarWidth(8),
    skipped 32 lines
  • ■ ■ ■ ■ ■ ■
    widgets/button/buttondemo/buttondemo.go
    skipped 24 lines
    25 25   "github.com/mum4k/termdash/cell"
    26 26   "github.com/mum4k/termdash/container"
    27 27   "github.com/mum4k/termdash/linestyle"
    28  - "github.com/mum4k/termdash/terminal/termbox"
     28 + "github.com/mum4k/termdash/terminal/tcell"
    29 29   "github.com/mum4k/termdash/terminal/terminalapi"
    30 30   "github.com/mum4k/termdash/widgets/button"
    31 31   "github.com/mum4k/termdash/widgets/segmentdisplay"
    32 32  )
    33 33   
    34 34  func main() {
    35  - t, err := termbox.New()
     35 + t, err := tcell.New()
    36 36   if err != nil {
    37 37   panic(err)
    38 38   }
    skipped 79 lines
  • ■ ■ ■ ■ ■ ■
    widgets/donut/donutdemo/donutdemo.go
    skipped 23 lines
    24 24   "github.com/mum4k/termdash/cell"
    25 25   "github.com/mum4k/termdash/container"
    26 26   "github.com/mum4k/termdash/linestyle"
    27  - "github.com/mum4k/termdash/terminal/termbox"
     27 + "github.com/mum4k/termdash/terminal/tcell"
    28 28   "github.com/mum4k/termdash/terminal/terminalapi"
    29 29   "github.com/mum4k/termdash/widgets/donut"
    30 30  )
    skipped 48 lines
    79 79  }
    80 80   
    81 81  func main() {
    82  - t, err := termbox.New()
     82 + t, err := tcell.New()
    83 83   if err != nil {
    84 84   panic(err)
    85 85   }
    skipped 9 lines
    95 95   }
    96 96   go playDonut(ctx, green, 0, 1, 250*time.Millisecond, playTypePercent)
    97 97   
    98  - blue, err := donut.New(donut.CellOpts(cell.FgColor(cell.ColorBlue)))
     98 + blue, err := donut.New(donut.CellOpts(cell.FgColor(cell.ColorNumber(33))))
    99 99   if err != nil {
    100 100   panic(err)
    101 101   }
    skipped 48 lines
  • ■ ■ ■ ■ ■ ■
    widgets/gauge/gaugedemo/gaugedemo.go
    skipped 23 lines
    24 24   "github.com/mum4k/termdash/cell"
    25 25   "github.com/mum4k/termdash/container"
    26 26   "github.com/mum4k/termdash/linestyle"
    27  - "github.com/mum4k/termdash/terminal/termbox"
     27 + "github.com/mum4k/termdash/terminal/tcell"
    28 28   "github.com/mum4k/termdash/terminal/terminalapi"
    29 29   "github.com/mum4k/termdash/widgets/gauge"
    30 30  )
    skipped 48 lines
    79 79  }
    80 80   
    81 81  func main() {
    82  - t, err := termbox.New()
     82 + t, err := tcell.New()
    83 83   if err != nil {
    84 84   panic(err)
    85 85   }
    skipped 12 lines
    98 98   
    99 99   absolute, err := gauge.New(
    100 100   gauge.Height(1),
    101  - gauge.Color(cell.ColorBlue),
     101 + gauge.Color(cell.ColorNumber(33)),
    102 102   gauge.Border(linestyle.Light),
    103 103   gauge.BorderTitle("Absolute progress"),
    104 104   )
    skipped 75 lines
  • ■ ■ ■ ■ ■ ■
    widgets/linechart/linechartdemo/linechartdemo.go
    skipped 24 lines
    25 25   "github.com/mum4k/termdash/cell"
    26 26   "github.com/mum4k/termdash/container"
    27 27   "github.com/mum4k/termdash/linestyle"
    28  - "github.com/mum4k/termdash/terminal/termbox"
     28 + "github.com/mum4k/termdash/terminal/tcell"
    29 29   "github.com/mum4k/termdash/terminal/terminalapi"
    30 30   "github.com/mum4k/termdash/widgets/linechart"
    31 31  )
    skipped 21 lines
    53 53   i = (i + 1) % len(inputs)
    54 54   rotated := append(inputs[i:], inputs[:i]...)
    55 55   if err := lc.Series("first", rotated,
    56  - linechart.SeriesCellOpts(cell.FgColor(cell.ColorBlue)),
     56 + linechart.SeriesCellOpts(cell.FgColor(cell.ColorNumber(33))),
    57 57   linechart.SeriesXLabels(map[int]string{
    58 58   0: "zero",
    59 59   }),
    skipped 14 lines
    74 74  }
    75 75   
    76 76  func main() {
    77  - t, err := termbox.New()
     77 + t, err := tcell.New()
    78 78   if err != nil {
    79 79   panic(err)
    80 80   }
    skipped 34 lines
  • ■ ■ ■ ■
    widgets/linechart/value_formatter.go
    skipped 127 lines
    128 128  }
    129 129   
    130 130  // valueFormatterSuffixWithTransformer is a factory that returns a formatter
    131  -// that will apply a tranform function to the received value before
     131 +// that will apply a transform function to the received value before
    132 132  // returning the decimal with suffix representation.
    133 133  func valueFormatterSuffixWithTransformer(decimals int, suffix string, transformFunc func(float64) float64) ValueFormatter {
    134 134   dFmt := suffixDecimalFormat(decimals, suffix)
    skipped 13 lines
  • ■ ■ ■ ■ ■ ■
    widgets/segmentdisplay/segmentdisplaydemo/segmentdisplaydemo.go
    skipped 23 lines
    24 24   "github.com/mum4k/termdash/cell"
    25 25   "github.com/mum4k/termdash/container"
    26 26   "github.com/mum4k/termdash/linestyle"
    27  - "github.com/mum4k/termdash/terminal/termbox"
     27 + "github.com/mum4k/termdash/terminal/tcell"
    28 28   "github.com/mum4k/termdash/terminal/terminalapi"
    29 29   "github.com/mum4k/termdash/widgets/segmentdisplay"
    30 30  )
    skipped 15 lines
    46 46   spacer = ":"
    47 47   }
    48 48   chunks := []*segmentdisplay.TextChunk{
    49  - segmentdisplay.NewChunk(parts[0], segmentdisplay.WriteCellOpts(cell.FgColor(cell.ColorBlue))),
     49 + segmentdisplay.NewChunk(parts[0], segmentdisplay.WriteCellOpts(cell.FgColor(cell.ColorNumber(33)))),
    50 50   segmentdisplay.NewChunk(spacer),
    51 51   segmentdisplay.NewChunk(parts[1], segmentdisplay.WriteCellOpts(cell.FgColor(cell.ColorRed))),
    52 52   }
    skipped 21 lines
    74 74  func rollText(ctx context.Context, sd *segmentdisplay.SegmentDisplay) {
    75 75   const text = "Termdash"
    76 76   colors := map[rune]cell.Color{
    77  - 'T': cell.ColorBlue,
     77 + 'T': cell.ColorNumber(33),
    78 78   'e': cell.ColorRed,
    79 79   'r': cell.ColorYellow,
    80  - 'm': cell.ColorBlue,
     80 + 'm': cell.ColorNumber(33),
    81 81   'd': cell.ColorGreen,
    82 82   'a': cell.ColorRed,
    83 83   's': cell.ColorGreen,
    skipped 29 lines
    113 113  }
    114 114   
    115 115  func main() {
    116  - t, err := termbox.New()
     116 + t, err := tcell.New()
    117 117   if err != nil {
    118 118   panic(err)
    119 119   }
    skipped 44 lines
  • ■ ■ ■ ■ ■ ■
    widgets/sparkline/sparklinedemo/sparklinedemo.go
    skipped 24 lines
    25 25   "github.com/mum4k/termdash/cell"
    26 26   "github.com/mum4k/termdash/container"
    27 27   "github.com/mum4k/termdash/linestyle"
    28  - "github.com/mum4k/termdash/terminal/termbox"
     28 + "github.com/mum4k/termdash/terminal/tcell"
    29 29   "github.com/mum4k/termdash/terminal/terminalapi"
    30 30   "github.com/mum4k/termdash/widgets/sparkline"
    31 31  )
    skipped 44 lines
    76 76  }
    77 77   
    78 78  func main() {
    79  - t, err := termbox.New()
     79 + t, err := tcell.New()
    80 80   if err != nil {
    81 81   panic(err)
    82 82   }
    skipped 1 lines
    84 84   
    85 85   ctx, cancel := context.WithCancel(context.Background())
    86 86   green, err := sparkline.New(
    87  - sparkline.Label("Green SparkLine", cell.FgColor(cell.ColorBlue)),
     87 + sparkline.Label("Green SparkLine", cell.FgColor(cell.ColorNumber(33))),
    88 88   sparkline.Color(cell.ColorGreen),
    89 89   )
    90 90   if err != nil {
    skipped 1 lines
    92 92   }
    93 93   go playSparkLine(ctx, green, 250*time.Millisecond)
    94 94   red, err := sparkline.New(
    95  - sparkline.Label("Red SparkLine", cell.FgColor(cell.ColorBlue)),
     95 + sparkline.Label("Red SparkLine", cell.FgColor(cell.ColorNumber(33))),
    96 96   sparkline.Color(cell.ColorRed),
    97 97   )
    98 98   if err != nil {
    skipped 55 lines
  • ■ ■ ■ ■ ■ ■
    widgets/text/options.go
    skipped 31 lines
    32 32   
    33 33  // options stores the provided options.
    34 34  type options struct {
     35 + scrollUp rune
     36 + scrollDown rune
    35 37   wrapMode wrap.Mode
    36 38   rollContent bool
    37 39   disableScrolling bool
    skipped 8 lines
    46 48  // newOptions returns a new options instance.
    47 49  func newOptions(opts ...Option) *options {
    48 50   opt := &options{
     51 + scrollUp: DefaultScrollUpRune,
     52 + scrollDown: DefaultScrollDownRune,
    49 53   mouseUpButton: DefaultScrollMouseButtonUp,
    50 54   mouseDownButton: DefaultScrollMouseButtonDown,
    51 55   keyUp: DefaultScrollKeyUp,
    skipped 31 lines
    83 87  func (o option) set(opts *options) {
    84 88   o(opts)
    85 89  }
     90 + 
     91 +// ScrollRunes configures the text widgets scroll runes, shown at the top and
     92 +// bottom of a scrollable text widget. If not provided, the default scroll
     93 +// runes will be used.
     94 +func ScrollRunes(up, down rune) Option {
     95 + return option(func(opts *options) {
     96 + opts.scrollUp = up
     97 + opts.scrollDown = down
     98 + })
     99 +}
     100 + 
     101 +// The default scroll runes for content scrolling
     102 +const (
     103 + DefaultScrollUpRune = '⇧'
     104 + DefaultScrollDownRune = '⇩'
     105 +)
    86 106   
    87 107  // WrapAtWords configures the text widget so that it automatically wraps lines
    88 108  // that are longer than the width of the widget at word boundaries. If not
    skipped 69 lines
  • ■ ■ ■ ■ ■ ■
    widgets/text/text.go
    skipped 124 lines
    125 125  func (t *Text) drawScrollUp(cvs *canvas.Canvas, cur image.Point, fromLine int) (bool, error) {
    126 126   height := cvs.Area().Dy()
    127 127   if cur.Y == 0 && height >= minLinesForMarkers && fromLine > 0 {
    128  - cells, err := cvs.SetCell(cur, '')
     128 + cells, err := cvs.SetCell(cur, t.opts.scrollUp)
    129 129   if err != nil {
    130 130   return false, err
    131 131   }
    skipped 12 lines
    144 144   height := cvs.Area().Dy()
    145 145   lines := len(t.wrapped)
    146 146   if cur.Y == height-1 && height >= minLinesForMarkers && height < lines-fromLine {
    147  - cells, err := cvs.SetCell(cur, '')
     147 + cells, err := cvs.SetCell(cur, t.opts.scrollDown)
    148 148   if err != nil {
    149 149   return false, err
    150 150   }
    skipped 137 lines
  • ■ ■ ■ ■ ■ ■
    widgets/text/text_test.go
    skipped 281 lines
    282 282   },
    283 283   },
    284 284   {
     285 + desc: "trims content when longer than canvas and draws a custom bottom scroll marker",
     286 + canvas: image.Rect(0, 0, 10, 3),
     287 + opts: []Option{
     288 + ScrollRunes('^', '.'),
     289 + },
     290 + writes: func(widget *Text) error {
     291 + return widget.Write("line0\nline1\nline2\nline3")
     292 + },
     293 + want: func(size image.Point) *faketerm.Terminal {
     294 + ft := faketerm.MustNew(size)
     295 + c := testcanvas.MustNew(ft.Area())
     296 + 
     297 + testdraw.MustText(c, "line0", image.Point{0, 0})
     298 + testdraw.MustText(c, "line1", image.Point{0, 1})
     299 + testdraw.MustText(c, ".", image.Point{0, 2})
     300 + testcanvas.MustApply(c, ft)
     301 + return ft
     302 + },
     303 + },
     304 + {
    285 305   desc: "scrolls down on mouse wheel down a line at a time",
    286 306   canvas: image.Rect(0, 0, 10, 3),
    287 307   writes: func(widget *Text) error {
    skipped 277 lines
    565 585   c := testcanvas.MustNew(ft.Area())
    566 586   
    567 587   testdraw.MustText(c, "⇧", image.Point{0, 0})
     588 + testdraw.MustText(c, "line2", image.Point{0, 1})
     589 + testdraw.MustText(c, "line3", image.Point{0, 2})
     590 + testcanvas.MustApply(c, ft)
     591 + return ft
     592 + },
     593 + },
     594 + {
     595 + desc: "rolls content upwards and draws a custom up scroll marker",
     596 + canvas: image.Rect(0, 0, 10, 3),
     597 + opts: []Option{
     598 + RollContent(),
     599 + ScrollRunes('^', '.'),
     600 + },
     601 + writes: func(widget *Text) error {
     602 + return widget.Write("line0\nline1\nline2\nline3")
     603 + },
     604 + want: func(size image.Point) *faketerm.Terminal {
     605 + ft := faketerm.MustNew(size)
     606 + c := testcanvas.MustNew(ft.Area())
     607 + 
     608 + testdraw.MustText(c, "^", image.Point{0, 0})
    568 609   testdraw.MustText(c, "line2", image.Point{0, 1})
    569 610   testdraw.MustText(c, "line3", image.Point{0, 2})
    570 611   testcanvas.MustApply(c, ft)
    skipped 293 lines
  • ■ ■ ■ ■ ■
    widgets/text/textdemo/textdemo.go
    skipped 21 lines
    22 22   "math/rand"
    23 23   "time"
    24 24   
     25 + "github.com/mum4k/termdash/terminal/tcell"
     26 + 
    25 27   "github.com/mum4k/termdash"
    26 28   "github.com/mum4k/termdash/cell"
    27 29   "github.com/mum4k/termdash/container"
    28 30   "github.com/mum4k/termdash/linestyle"
    29  - "github.com/mum4k/termdash/terminal/termbox"
    30 31   "github.com/mum4k/termdash/terminal/terminalapi"
    31 32   "github.com/mum4k/termdash/widgets/text"
    32 33  )
    skipped 34 lines
    67 68  }
    68 69   
    69 70  func main() {
    70  - t, err := termbox.New()
     71 + t, err := tcell.New()
    71 72   if err != nil {
    72 73   panic(err)
    73 74   }
    skipped 31 lines
    105 106   if err := wrapped.Write("Supports", text.WriteCellOpts(cell.FgColor(cell.ColorRed))); err != nil {
    106 107   panic(err)
    107 108   }
    108  - if err := wrapped.Write(" colors", text.WriteCellOpts(cell.FgColor(cell.ColorBlue))); err != nil {
     109 + if err := wrapped.Write(" colors", text.WriteCellOpts(cell.FgColor(cell.ColorNumber(33)))); err != nil {
     110 + panic(err)
     111 + }
     112 + if err := wrapped.Write(" and"); err != nil {
     113 + panic(err)
     114 + }
     115 + if err := wrapped.Write(" font ", text.WriteCellOpts(cell.Bold(), cell.Italic())); err != nil {
     116 + panic(err)
     117 + }
     118 + if err := wrapped.Write("modifiers", text.WriteCellOpts(cell.Underline(), cell.Italic())); err != nil {
    109 119   panic(err)
    110 120   }
    111 121   if err := wrapped.Write(". Wraps long lines at rune boundaries if the WrapAtRunes() option is provided.\nSupports newline character to\ncreate\nnewlines\nmanually.\nTrims the content if it is too long.\n\n\n\nToo long."); err != nil {
    skipped 69 lines
  • ■ ■ ■ ■ ■ ■
    widgets/textinput/textinputdemo/textinputdemo.go
    skipped 25 lines
    26 26   "github.com/mum4k/termdash/container/grid"
    27 27   "github.com/mum4k/termdash/keyboard"
    28 28   "github.com/mum4k/termdash/linestyle"
    29  - "github.com/mum4k/termdash/terminal/termbox"
     29 + "github.com/mum4k/termdash/terminal/tcell"
    30 30   "github.com/mum4k/termdash/widgets/button"
    31 31   "github.com/mum4k/termdash/widgets/segmentdisplay"
    32 32   "github.com/mum4k/termdash/widgets/textinput"
    skipped 27 lines
    60 60  // Exists when the context expires.
    61 61  func rollText(ctx context.Context, sd *segmentdisplay.SegmentDisplay, updateText <-chan string) {
    62 62   colors := []cell.Color{
    63  - cell.ColorBlue,
     63 + cell.ColorNumber(33),
    64 64   cell.ColorRed,
    65 65   cell.ColorYellow,
    66  - cell.ColorBlue,
     66 + cell.ColorNumber(33),
    67 67   cell.ColorGreen,
    68 68   cell.ColorRed,
    69 69   cell.ColorGreen,
    skipped 40 lines
    110 110  }
    111 111   
    112 112  func main() {
    113  - t, err := termbox.New()
     113 + t, err := tcell.New()
    114 114   if err != nil {
    115 115   panic(err)
    116 116   }
    skipped 10 lines
    127 127   go rollText(ctx, rollingSD, updateText)
    128 128   
    129 129   input, err := textinput.New(
    130  - textinput.Label("New text:", cell.FgColor(cell.ColorBlue)),
     130 + textinput.Label("New text:", cell.FgColor(cell.ColorNumber(33))),
    131 131   textinput.MaxWidthCells(20),
    132 132   textinput.Border(linestyle.Light),
    133 133   textinput.PlaceHolder("Enter any text"),
    skipped 98 lines
Please wait...
Page is in error, reload to recover