2019-02-04 13:49:05 +08:00
|
|
|
// Copyright 2019 Google Inc.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2019-02-04 13:39:51 +08:00
|
|
|
package attrrange
|
|
|
|
|
|
|
|
import (
|
2019-02-04 13:48:26 +08:00
|
|
|
"log"
|
2019-02-04 13:39:51 +08:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/kylelemons/godebug/pretty"
|
2019-02-04 13:48:26 +08:00
|
|
|
"github.com/mum4k/termdash/cell"
|
2019-02-04 13:39:51 +08:00
|
|
|
)
|
|
|
|
|
2019-02-04 13:48:26 +08:00
|
|
|
func Example() {
|
|
|
|
// Caller has a slice of some attributes, like a cell color that applies
|
|
|
|
// to a portion of text.
|
|
|
|
attrs := []cell.Color{cell.ColorRed, cell.ColorBlue}
|
|
|
|
redIdx := 0
|
|
|
|
blueIdx := 1
|
|
|
|
|
|
|
|
// This is the text the colors apply to.
|
|
|
|
const text = "HelloWorld"
|
|
|
|
|
|
|
|
// Assuming that we want the word "Hello" in red and the word "World" in
|
|
|
|
// green, we can set our ranges as follows:
|
|
|
|
tr := NewTracker()
|
|
|
|
if err := tr.Add(0, len("Hello"), redIdx); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
if err := tr.Add(len("Hello")+1, len(text), blueIdx); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now to get the index into attrs (i.e. the color) for a particular
|
|
|
|
// character, we can do:
|
|
|
|
for i, c := range text {
|
|
|
|
ar, err := tr.ForPosition(i)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
log.Printf("character at text[%d] = %q, color index %d = %v, range low:%d, high:%d", i, c, ar.AttrIdx, attrs[ar.AttrIdx], ar.Low, ar.High)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-04 13:39:51 +08:00
|
|
|
func TestForPosition(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
desc string
|
|
|
|
// if not nil, called before calling ForPosition.
|
|
|
|
// Can add ranges.
|
|
|
|
update func(*Tracker) error
|
|
|
|
pos int
|
|
|
|
want *AttrRange
|
2019-02-05 13:05:31 +08:00
|
|
|
wantErr bool
|
2019-02-04 13:39:51 +08:00
|
|
|
wantUpdateErr bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
desc: "fails when no ranges given",
|
|
|
|
pos: 0,
|
2019-02-05 13:05:31 +08:00
|
|
|
wantErr: true,
|
2019-02-04 13:39:51 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "fails to add a duplicate",
|
|
|
|
update: func(tr *Tracker) error {
|
|
|
|
if err := tr.Add(2, 5, 40); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tr.Add(2, 3, 41)
|
|
|
|
},
|
|
|
|
wantUpdateErr: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "fails when multiple given ranges, position falls before them",
|
|
|
|
update: func(tr *Tracker) error {
|
|
|
|
if err := tr.Add(2, 5, 40); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tr.Add(5, 10, 41)
|
|
|
|
},
|
|
|
|
pos: 1,
|
2019-02-05 13:05:31 +08:00
|
|
|
wantErr: true,
|
2019-02-04 13:39:51 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "multiple given options, position falls on the lower",
|
|
|
|
update: func(tr *Tracker) error {
|
|
|
|
if err := tr.Add(2, 5, 40); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tr.Add(5, 10, 41)
|
|
|
|
},
|
|
|
|
pos: 2,
|
|
|
|
want: newAttrRange(2, 5, 40),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "multiple given options, position falls between them",
|
|
|
|
update: func(tr *Tracker) error {
|
|
|
|
if err := tr.Add(2, 5, 40); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tr.Add(5, 10, 41)
|
|
|
|
},
|
|
|
|
pos: 4,
|
|
|
|
want: newAttrRange(2, 5, 40),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "multiple given options, position falls on the higher",
|
|
|
|
update: func(tr *Tracker) error {
|
|
|
|
if err := tr.Add(2, 5, 40); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tr.Add(5, 10, 41)
|
|
|
|
},
|
|
|
|
pos: 5,
|
|
|
|
want: newAttrRange(5, 10, 41),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
desc: "multiple given options, position falls after them",
|
|
|
|
update: func(tr *Tracker) error {
|
|
|
|
if err := tr.Add(2, 5, 40); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return tr.Add(5, 10, 41)
|
|
|
|
},
|
|
|
|
pos: 10,
|
2019-02-05 13:05:31 +08:00
|
|
|
wantErr: true,
|
2019-02-04 13:39:51 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range tests {
|
|
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
|
|
tr := NewTracker()
|
|
|
|
if tc.update != nil {
|
|
|
|
err := tc.update(tr)
|
|
|
|
if (err != nil) != tc.wantUpdateErr {
|
|
|
|
t.Errorf("tc.update => unexpected error:%v, wantUpdateErr:%v", err, tc.wantUpdateErr)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
got, err := tr.ForPosition(tc.pos)
|
2019-02-05 13:05:31 +08:00
|
|
|
if (err != nil) != tc.wantErr {
|
2019-02-04 13:39:51 +08:00
|
|
|
t.Errorf("ForPosition => unexpected error:%v, wantErr:%v", err, tc.wantErr)
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := pretty.Compare(tc.want, got); diff != "" {
|
|
|
|
t.Errorf("ForPosition => unexpected diff (-want, +got):\n%s", diff)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|