Bugfixes and refactoring
Bugfixes: - Fixes a bug which placed the tree dots (…) for overflown list on the wrong position. Refactoring - Renamed `TextRender` to `TextRenderer` - Renamed `NoopRenderer` to `PlainRenderer` - Renamed `NoopRendererFactory` to `PlainRendererFactory`
This commit is contained in:
parent
769ce01ae8
commit
3c08053c57
@ -19,8 +19,8 @@ func commonList() *termui.List {
|
|||||||
|
|
||||||
list := termui.NewList()
|
list := termui.NewList()
|
||||||
list.Items = strs
|
list.Items = strs
|
||||||
list.Height = 20
|
list.Height = 15
|
||||||
list.Width = 25
|
list.Width = 26
|
||||||
list.RendererFactory = termui.MarkdownTextRendererFactory{}
|
list.RendererFactory = termui.MarkdownTextRendererFactory{}
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
63
list.go
63
list.go
@ -42,49 +42,54 @@ func NewList() *List {
|
|||||||
l.Overflow = "hidden"
|
l.Overflow = "hidden"
|
||||||
l.ItemFgColor = theme.ListItemFg
|
l.ItemFgColor = theme.ListItemFg
|
||||||
l.ItemBgColor = theme.ListItemBg
|
l.ItemBgColor = theme.ListItemBg
|
||||||
l.RendererFactory = NoopRendererFactory{}
|
l.RendererFactory = PlainRendererFactory{}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buffer implements Bufferer interface.
|
// Buffer implements Bufferer interface.
|
||||||
func (l *List) Buffer() []Point {
|
func (l *List) Buffer() []Point {
|
||||||
ps := l.Block.Buffer()
|
buffer := l.Block.Buffer()
|
||||||
switch l.Overflow {
|
|
||||||
case "wrap":
|
|
||||||
y := 0
|
|
||||||
for _, item := range l.Items {
|
|
||||||
x := 0
|
|
||||||
|
|
||||||
renderer := l.RendererFactory.TextRenderer(item)
|
breakLoop := func(y int) bool {
|
||||||
sequence := renderer.Render(l.ItemFgColor, l.ItemBgColor)
|
return y+1 > l.innerHeight
|
||||||
for n := range []rune(sequence.NormalizedText) {
|
}
|
||||||
point, width := sequence.PointAt(n, x+l.innerX, y+l.innerY)
|
y := 0
|
||||||
|
|
||||||
if width+x <= l.innerWidth {
|
MainLoop:
|
||||||
ps = append(ps, point)
|
for _, item := range l.Items {
|
||||||
x += width
|
x := 0
|
||||||
} else {
|
bg, fg := l.ItemFgColor, l.ItemBgColor
|
||||||
|
renderer := l.RendererFactory.TextRenderer(item)
|
||||||
|
sequence := renderer.Render(bg, fg)
|
||||||
|
|
||||||
|
for n := range []rune(sequence.NormalizedText) {
|
||||||
|
point, width := sequence.PointAt(n, x+l.innerX, y+l.innerY)
|
||||||
|
|
||||||
|
if width+x <= l.innerWidth {
|
||||||
|
buffer = append(buffer, point)
|
||||||
|
x += width
|
||||||
|
} else {
|
||||||
|
if l.Overflow == "wrap" {
|
||||||
y++
|
y++
|
||||||
|
if breakLoop(y) {
|
||||||
|
break MainLoop
|
||||||
|
}
|
||||||
x = 0
|
x = 0
|
||||||
|
} else {
|
||||||
|
dotR := []rune(dot)[0]
|
||||||
|
dotX := l.innerWidth + l.innerX - charWidth(dotR)
|
||||||
|
p := newPointWithAttrs(dotR, dotX, y+l.innerY, bg, fg)
|
||||||
|
buffer = append(buffer, p)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
y++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "hidden":
|
y++
|
||||||
trimItems := l.Items
|
if breakLoop(y) {
|
||||||
if len(trimItems) > l.innerHeight {
|
break MainLoop
|
||||||
trimItems = trimItems[:l.innerHeight]
|
|
||||||
}
|
|
||||||
|
|
||||||
for y, item := range trimItems {
|
|
||||||
text := TrimStrIfAppropriate(item, l.innerWidth)
|
|
||||||
render := l.RendererFactory.TextRenderer(text)
|
|
||||||
sequence := render.RenderSequence(0, -1, l.ItemFgColor, l.ItemBgColor)
|
|
||||||
t, _ := sequence.Buffer(l.innerX, y+l.innerY)
|
|
||||||
ps = append(ps, t...)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.Block.chopOverflow(ps)
|
return l.Block.chopOverflow(buffer)
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TextRender adds common methods for rendering a text on screeen.
|
// TextRenderer adds common methods for rendering a text on screeen.
|
||||||
type TextRender interface {
|
type TextRenderer interface {
|
||||||
NormalizedText() string
|
NormalizedText() string
|
||||||
Render(lastColor, background Attribute) RenderedSequence
|
Render(lastColor, background Attribute) RenderedSequence
|
||||||
RenderSequence(start, end int, lastColor, background Attribute) RenderedSequence
|
RenderSequence(start, end int, lastColor, background Attribute) RenderedSequence
|
||||||
@ -14,7 +14,7 @@ type TextRender interface {
|
|||||||
|
|
||||||
// TextRendererFactory is factory for creating text renderers.
|
// TextRendererFactory is factory for creating text renderers.
|
||||||
type TextRendererFactory interface {
|
type TextRendererFactory interface {
|
||||||
TextRenderer(text string) TextRender
|
TextRenderer(text string) TextRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkdownRegex is used by MarkdownTextRenderer to determine how to format the
|
// MarkdownRegex is used by MarkdownTextRenderer to determine how to format the
|
||||||
@ -134,7 +134,7 @@ func (r MarkdownTextRenderer) RenderSequence(start, end int, lastColor, backgrou
|
|||||||
type MarkdownTextRendererFactory struct{}
|
type MarkdownTextRendererFactory struct{}
|
||||||
|
|
||||||
// TextRenderer returns a MarkdownTextRenderer instance.
|
// TextRenderer returns a MarkdownTextRenderer instance.
|
||||||
func (f MarkdownTextRendererFactory) TextRenderer(text string) TextRender {
|
func (f MarkdownTextRendererFactory) TextRenderer(text string) TextRenderer {
|
||||||
return MarkdownTextRenderer{text}
|
return MarkdownTextRenderer{text}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,19 +207,19 @@ func (s *RenderedSequence) PointAt(n, x, y int) (Point, int) {
|
|||||||
return Point{char, s.BackgroundColor, color, x, y}, charWidth(char)
|
return Point{char, s.BackgroundColor, color, x, y}, charWidth(char)
|
||||||
}
|
}
|
||||||
|
|
||||||
// A NoopRenderer does not render the text at all.
|
// A PlainRenderer does not render the text at all.
|
||||||
type NoopRenderer struct {
|
type PlainRenderer struct {
|
||||||
Text string
|
Text string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NormalizedText returns the text given in
|
// NormalizedText returns the text given in
|
||||||
func (r NoopRenderer) NormalizedText() string {
|
func (r PlainRenderer) NormalizedText() string {
|
||||||
return r.Text
|
return r.Text
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderSequence returns a RenderedSequence that does not have any color
|
// RenderSequence returns a RenderedSequence that does not have any color
|
||||||
// sequences.
|
// sequences.
|
||||||
func (r NoopRenderer) RenderSequence(start, end int, lastColor, background Attribute) RenderedSequence {
|
func (r PlainRenderer) RenderSequence(start, end int, lastColor, background Attribute) RenderedSequence {
|
||||||
runes := []rune(r.Text)
|
runes := []rune(r.Text)
|
||||||
if end < 0 {
|
if end < 0 {
|
||||||
end = len(runes)
|
end = len(runes)
|
||||||
@ -231,15 +231,15 @@ func (r NoopRenderer) RenderSequence(start, end int, lastColor, background Attri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Render just like RenderSequence
|
// Render just like RenderSequence
|
||||||
func (r NoopRenderer) Render(lastColor, background Attribute) RenderedSequence {
|
func (r PlainRenderer) Render(lastColor, background Attribute) RenderedSequence {
|
||||||
return r.RenderSequence(0, -1, lastColor, background)
|
return r.RenderSequence(0, -1, lastColor, background)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoopRendererFactory is a TextRendererFactory for
|
// PlainRendererFactory is a TextRendererFactory for
|
||||||
// the NoopRenderer.
|
// the PlainRenderer.
|
||||||
type NoopRendererFactory struct{}
|
type PlainRendererFactory struct{}
|
||||||
|
|
||||||
// TextRenderer returns a NoopRenderer instance.
|
// TextRenderer returns a PlainRenderer instance.
|
||||||
func (f NoopRendererFactory) TextRenderer(text string) TextRender {
|
func (f PlainRendererFactory) TextRenderer(text string) TextRenderer {
|
||||||
return NoopRenderer{text}
|
return PlainRenderer{text}
|
||||||
}
|
}
|
||||||
|
@ -10,17 +10,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestTextRender_TestInterface(t *testing.T) {
|
func TestTextRender_TestInterface(t *testing.T) {
|
||||||
var inter *TextRender
|
var inter *TextRenderer
|
||||||
|
|
||||||
assert.Implements(t, inter, new(MarkdownTextRenderer))
|
assert.Implements(t, inter, new(MarkdownTextRenderer))
|
||||||
assert.Implements(t, inter, new(NoopRenderer))
|
assert.Implements(t, inter, new(PlainRenderer))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTextRendererFactory_TestInterface(t *testing.T) {
|
func TestTextRendererFactory_TestInterface(t *testing.T) {
|
||||||
var inter *TextRendererFactory
|
var inter *TextRendererFactory
|
||||||
|
|
||||||
assert.Implements(t, inter, new(MarkdownTextRendererFactory))
|
assert.Implements(t, inter, new(MarkdownTextRendererFactory))
|
||||||
assert.Implements(t, inter, new(NoopRendererFactory))
|
assert.Implements(t, inter, new(PlainRendererFactory))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMarkdownTextRenderer_normalizeText(t *testing.T) {
|
func TestMarkdownTextRenderer_normalizeText(t *testing.T) {
|
||||||
@ -232,31 +232,31 @@ func TestRenderedSequence_PointAt(t *testing.T) {
|
|||||||
AssertPoint(t, pointAt(10, 7, 1), 'd', 7, 1)
|
AssertPoint(t, pointAt(10, 7, 1), 'd', 7, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTestNoopRenderer() NoopRenderer {
|
func getTestPlainRenderer() PlainRenderer {
|
||||||
return NoopRenderer{"[Hello](red) \x1b[31mworld"}
|
return PlainRenderer{"[Hello](red) \x1b[31mworld"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoopRenderer_NormalizedText(t *testing.T) {
|
func TestPlainRenderer_NormalizedText(t *testing.T) {
|
||||||
r := getTestNoopRenderer()
|
r := getTestPlainRenderer()
|
||||||
assert.Equal(t, "[Hello](red) \x1b[31mworld", r.NormalizedText())
|
assert.Equal(t, "[Hello](red) \x1b[31mworld", r.NormalizedText())
|
||||||
assert.Equal(t, "[Hello](red) \x1b[31mworld", r.Text)
|
assert.Equal(t, "[Hello](red) \x1b[31mworld", r.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoopRenderer_Render(t *testing.T) {
|
func TestPlainRenderer_Render(t *testing.T) {
|
||||||
renderer := getTestNoopRenderer()
|
renderer := getTestPlainRenderer()
|
||||||
got := renderer.Render(5, 7)
|
got := renderer.Render(5, 7)
|
||||||
assertRenderSequence(t, got, 5, 7, "[Hello](red) \x1b[31mworld", 0)
|
assertRenderSequence(t, got, 5, 7, "[Hello](red) \x1b[31mworld", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoopRenderer_RenderSequence(t *testing.T) {
|
func TestPlainRenderer_RenderSequence(t *testing.T) {
|
||||||
renderer := getTestNoopRenderer()
|
renderer := getTestPlainRenderer()
|
||||||
got := renderer.RenderSequence(3, 5, 9, 1)
|
got := renderer.RenderSequence(3, 5, 9, 1)
|
||||||
assertRenderSequence(t, got, 9, 1, "ll", 0)
|
assertRenderSequence(t, got, 9, 1, "ll", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoopRendererFactory(t *testing.T) {
|
func TestPlainRendererFactory(t *testing.T) {
|
||||||
factory := NoopRendererFactory{}
|
factory := PlainRendererFactory{}
|
||||||
expected := NoopRenderer{"Hello world"}
|
expected := PlainRenderer{"Hello world"}
|
||||||
assert.Equal(t, factory.TextRenderer("Hello world"), expected)
|
assert.Equal(t, factory.TextRenderer("Hello world"), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user