mirror of https://github.com/mum4k/termdash.git
Defining options for text written to the widget.
Each set of options applies to a range of characters equal to the length of the text added. E.g. on write calls like: Write("text", opts1) Write("long text", opts2) The two passed options will be stored as: opts1 for byte range low:0, high:4 opts2 for byte range low:4, high:13 The text itself will be stored in a bytes.Buffer.
This commit is contained in:
parent
a824210882
commit
e786777410
|
@ -0,0 +1,103 @@
|
|||
package text
|
||||
|
||||
// write_options.go contains options used when writing content to the Text widget.
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/mum4k/termdash/cell"
|
||||
)
|
||||
|
||||
// WriteOption is used to provide options to Write().
|
||||
type WriteOption interface {
|
||||
// set sets the provided option.
|
||||
set(*writeOptions)
|
||||
}
|
||||
|
||||
// writeOptions stores the provided options.
|
||||
type writeOptions struct {
|
||||
cellOpts *cell.Options
|
||||
}
|
||||
|
||||
// newWriteOptions returns new writeOptions instance.
|
||||
func newWriteOptions(wOpts ...WriteOption) *writeOptions {
|
||||
wo := &writeOptions{
|
||||
cellOpts: cell.NewOptions(),
|
||||
}
|
||||
for _, o := range wOpts {
|
||||
o.set(wo)
|
||||
}
|
||||
return wo
|
||||
}
|
||||
|
||||
// writeOption implements WriteOption.
|
||||
type writeOption func(*writeOptions)
|
||||
|
||||
// set implements WriteOption.set.
|
||||
func (wo writeOption) set(wOpts *writeOptions) {
|
||||
wo(wOpts)
|
||||
}
|
||||
|
||||
// WriteCellOpts sets options on the cells that contain the text.
|
||||
func WriteCellOpts(opts ...cell.Option) WriteOption {
|
||||
return writeOption(func(wOpts *writeOptions) {
|
||||
wOpts.cellOpts = cell.NewOptions(opts...)
|
||||
})
|
||||
}
|
||||
|
||||
// optsRange are write options that apply to a range of bytes in the text.
|
||||
type optsRange struct {
|
||||
// low is the first byte where these options apply.
|
||||
low int
|
||||
|
||||
// high is the end of the range. The opts apply to all bytes in range low
|
||||
// <= b < high.
|
||||
high int
|
||||
|
||||
// opts are the options provided at a call to Write().
|
||||
opts *writeOptions
|
||||
}
|
||||
|
||||
// newOptsRange returns a new optsRange.
|
||||
func newOptsRange(low, high int, opts *writeOptions) *optsRange {
|
||||
return &optsRange{
|
||||
low: low,
|
||||
high: high,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
// givenWOpts stores the write options provided on all the calls to Write().
|
||||
// The options are keyed by their low indices.
|
||||
type givenWOpts map[int]*optsRange
|
||||
|
||||
// newGivenWOpts returns a new givenWOpts instance.
|
||||
func newGivenWOpts() givenWOpts {
|
||||
return givenWOpts{}
|
||||
}
|
||||
|
||||
// forPosition returns write options that apply to character at the specified
|
||||
// byte position.
|
||||
func (g givenWOpts) forPosition(pos int) *optsRange {
|
||||
if or, ok := g[pos]; ok {
|
||||
return or
|
||||
}
|
||||
|
||||
var keys []int
|
||||
for k := range g {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Ints(keys)
|
||||
|
||||
res := newOptsRange(0, 0, newWriteOptions())
|
||||
for _, k := range keys {
|
||||
or := g[k]
|
||||
if or.low > pos {
|
||||
break
|
||||
}
|
||||
if or.high > pos {
|
||||
res = or
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
package text
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kylelemons/godebug/pretty"
|
||||
"github.com/mum4k/termdash/cell"
|
||||
)
|
||||
|
||||
func TestGivenWOpts(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
given givenWOpts
|
||||
pos int
|
||||
want *optsRange
|
||||
}{
|
||||
{
|
||||
desc: "no write options given results in defaults",
|
||||
given: nil,
|
||||
pos: 1,
|
||||
want: &optsRange{
|
||||
low: 0,
|
||||
high: 0,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "multiple given options, position falls before them",
|
||||
given: givenWOpts{
|
||||
2: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
5: &optsRange{
|
||||
low: 5,
|
||||
high: 10,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorRed,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pos: 1,
|
||||
want: &optsRange{
|
||||
low: 0,
|
||||
high: 0,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "multiple given options, position falls on the lower",
|
||||
given: givenWOpts{
|
||||
2: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
5: &optsRange{
|
||||
low: 5,
|
||||
high: 10,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorRed,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pos: 2,
|
||||
want: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "multiple given options, position falls between them",
|
||||
given: givenWOpts{
|
||||
2: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
5: &optsRange{
|
||||
low: 5,
|
||||
high: 10,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorRed,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pos: 4,
|
||||
want: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "multiple given options, position falls on the higher",
|
||||
given: givenWOpts{
|
||||
2: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
5: &optsRange{
|
||||
low: 5,
|
||||
high: 10,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorRed,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pos: 5,
|
||||
want: &optsRange{
|
||||
low: 5,
|
||||
high: 10,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorRed,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "multiple given options, position falls after them",
|
||||
given: givenWOpts{
|
||||
2: &optsRange{
|
||||
low: 2,
|
||||
high: 5,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorBlue,
|
||||
},
|
||||
},
|
||||
},
|
||||
5: &optsRange{
|
||||
low: 5,
|
||||
high: 10,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{
|
||||
FgColor: cell.ColorRed,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
pos: 10,
|
||||
want: &optsRange{
|
||||
low: 0,
|
||||
high: 0,
|
||||
opts: &writeOptions{
|
||||
cellOpts: &cell.Options{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
got := tc.given.forPosition(tc.pos)
|
||||
if diff := pretty.Compare(tc.want, got); diff != "" {
|
||||
t.Errorf("forPosition => unexpected diff (-want, +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue