blockelement.go

 1package ansi
 2
 3import (
 4	"bytes"
 5	"fmt"
 6	"io"
 7
 8	"github.com/charmbracelet/x/cellbuf"
 9)
10
11// BlockElement provides a render buffer for children of a block element.
12// After all children have been rendered into it, it applies indentation and
13// margins around them and writes everything to the parent rendering buffer.
14type BlockElement struct {
15	Block   *bytes.Buffer
16	Style   StyleBlock
17	Margin  bool
18	Newline bool
19}
20
21// Render renders a BlockElement.
22func (e *BlockElement) Render(w io.Writer, ctx RenderContext) error {
23	bs := ctx.blockStack
24	bs.Push(*e)
25
26	_, _ = renderText(w, bs.Parent().Style.StylePrimitive, e.Style.BlockPrefix)
27	_, _ = renderText(bs.Current().Block, bs.Current().Style.StylePrimitive, e.Style.Prefix)
28	return nil
29}
30
31// Finish finishes rendering a BlockElement.
32func (e *BlockElement) Finish(w io.Writer, ctx RenderContext) error {
33	bs := ctx.blockStack
34
35	if e.Margin { //nolint: nestif
36		s := cellbuf.Wrap(
37			bs.Current().Block.String(),
38			int(bs.Width(ctx)), //nolint: gosec
39			" ,.;-+|",
40		)
41
42		mw := NewMarginWriter(ctx, w, bs.Current().Style)
43		if _, err := io.WriteString(mw, s); err != nil {
44			return fmt.Errorf("glamour: error writing to writer: %w", err)
45		}
46
47		if e.Newline {
48			if _, err := io.WriteString(mw, "\n"); err != nil {
49				return fmt.Errorf("glamour: error writing to writer: %w", err)
50			}
51		}
52	} else {
53		_, err := bs.Parent().Block.Write(bs.Current().Block.Bytes())
54		if err != nil {
55			return fmt.Errorf("glamour: error writing to writer: %w", err)
56		}
57	}
58
59	_, _ = renderText(w, bs.Current().Style.StylePrimitive, e.Style.Suffix)
60	_, _ = renderText(w, bs.Parent().Style.StylePrimitive, e.Style.BlockSuffix)
61
62	bs.Current().Block.Reset()
63	bs.Pop()
64	return nil
65}