exp: golang.org/x/exp/shiny/text Index | Examples | Files

package text

import "golang.org/x/exp/shiny/text"

Package text lays out paragraphs of text.

A body of text is laid out into a Frame: Frames contain Paragraphs (stacked vertically), Paragraphs contain Lines (stacked vertically), and Lines contain Boxes (stacked horizontally). Each Box holds a []byte slice of the text. For example, to simply print a Frame's text from start to finish:

var f *text.Frame = etc
for p := f.FirstParagraph(); p != nil; p = p.Next(f) {
	for l := p.FirstLine(f); l != nil; l = l.Next(f) {
		for b := l.FirstBox(f); b != nil; b = b.Next(f) {
			fmt.Print(b.Text(f))
		}
	}
}

A Frame's structure (the tree of Paragraphs, Lines and Boxes), and its []byte text, are not modified directly. Instead, a Frame's maximum width can be re-sized, and text can be added and removed via Carets (which implement standard io interfaces). For example, to add some words to the end of a frame:

var f *text.Frame = etc
c := f.NewCaret()
c.Seek(0, text.SeekEnd)
c.WriteString("Not with a bang but a whimper.\n")
c.Close()

Either way, such modifications can cause re-layout, which can add or remove Paragraphs, Lines and Boxes. The underlying memory for such structs can be re-used, so pointer values, such as of type *Box, should not be held over such modifications.

Code:

package main

import (
    "fmt"
    "image"
    "os"

    "golang.org/x/exp/shiny/text"
    "golang.org/x/image/font"
    "golang.org/x/image/math/fixed"
)

// toyFace implements the font.Face interface by measuring every rune's width
// as 1 pixel.
type toyFace struct{}

func (toyFace) Close() error {
    return nil
}

func (toyFace) Glyph(dot fixed.Point26_6, r rune) (image.Rectangle, image.Image, image.Point, fixed.Int26_6, bool) {
    panic("unimplemented")
}

func (toyFace) GlyphBounds(r rune) (fixed.Rectangle26_6, fixed.Int26_6, bool) {
    panic("unimplemented")
}

func (toyFace) GlyphAdvance(r rune) (fixed.Int26_6, bool) {
    return fixed.I(1), true
}

func (toyFace) Kern(r0, r1 rune) fixed.Int26_6 {
    return 0
}

func (toyFace) Metrics() font.Metrics {
    return font.Metrics{}
}

func printFrame(f *text.Frame, softReturnsOnly bool) {
    for p := f.FirstParagraph(); p != nil; p = p.Next(f) {
        for l := p.FirstLine(f); l != nil; l = l.Next(f) {
            for b := l.FirstBox(f); b != nil; b = b.Next(f) {
                if softReturnsOnly {
                    os.Stdout.Write(b.TrimmedText(f))
                } else {
                    os.Stdout.Write(b.Text(f))
                }
            }
            if softReturnsOnly {
                fmt.Println()
            }
        }
    }
}

func main() {
    var f text.Frame
    f.SetFace(toyFace{})
    f.SetMaxWidth(fixed.I(60))

    c := f.NewCaret()
    c.WriteString(mobyDick)
    c.Close()

    fmt.Println("====")
    printFrame(&f, false)
    fmt.Println("====")
    fmt.Println("123456789_123456789_123456789_123456789_123456789_123456789_")
    printFrame(&f, true)
    fmt.Println("====")

}

const mobyDick = "CHAPTER 1. Loomings.\nCall me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world...\n"

Index

Examples

Package Files

caret.go text.go

Constants

const (
    SeekSet int = 0
    SeekCur int = 1
    SeekEnd int = 2
)

These constants are equal to os.SEEK_SET, os.SEEK_CUR and os.SEEK_END, understood by the io.Seeker interface, and are provided so that users of this package don't have to explicitly import "os".

type Box Uses

type Box struct {
    // contains filtered or unexported fields
}

Box holds a contiguous run of text.

func (*Box) Next Uses

func (b *Box) Next(f *Frame) *Box

Next returns the next Box after this one in the Line.

f is the Frame that contains the Box.

func (*Box) Text Uses

func (b *Box) Text(f *Frame) []byte

Text returns the Box's text.

f is the Frame that contains the Box.

func (*Box) TrimmedText Uses

func (b *Box) TrimmedText(f *Frame) []byte

TrimmedText returns the Box's text, trimmed right of any white space if it is the last Box in its Line.

f is the Frame that contains the Box.

type Caret Uses

type Caret struct {
    // contains filtered or unexported fields
}

Caret is a location in a Frame's text, and is the mechanism for adding and removing bytes of text. Conceptually, a Caret and a Frame's text is like an int c and a []byte t such that the text before and after that Caret is t[:c] and t[c:]. That byte-count location remains unchanged even when a Frame is re-sized and laid out into a new tree of Paragraphs, Lines and Boxes.

A Frame can have multiple open Carets. For example, the beginning and end of a text selection can be represented by two Carets. Multiple Carets for the one Frame are not safe to use concurrently, but it is valid to interleave such operations sequentially. For example, if two Carets c0 and c1 for the one Frame are positioned at the 10th and 20th byte, and 4 bytes are written to c0, inserting what becomes the equivalent of text[10:14], then c0's position is updated to be 14 but c1's position is also updated to be 24.

func (*Caret) Close Uses

func (c *Caret) Close() error

Close closes the Caret.

func (*Caret) Delete Uses

func (c *Caret) Delete(dir Direction, nBytes int) (dBytes int)

Delete deletes nBytes bytes in the specified direction from the Caret's location. It returns the number of bytes deleted, which can be fewer than that requested if it hits the beginning or end of the Frame.

func (*Caret) DeleteRunes Uses

func (c *Caret) DeleteRunes(dir Direction, nRunes int) (dRunes, dBytes int)

DeleteRunes deletes nRunes runes in the specified direction from the Caret's location. It returns the number of runes and bytes deleted, which can be fewer than that requested if it hits the beginning or end of the Frame.

func (*Caret) Read Uses

func (c *Caret) Read(buf []byte) (n int, err error)

Read satisfies the io.Reader interface by copying those bytes after the Caret and incrementing the Caret.

func (*Caret) ReadByte Uses

func (c *Caret) ReadByte() (x byte, err error)

ReadByte returns the next byte after the Caret and increments the Caret.

func (*Caret) ReadRune Uses

func (c *Caret) ReadRune() (r rune, size int, err error)

ReadRune returns the next rune after the Caret and increments the Caret.

func (*Caret) Seek Uses

func (c *Caret) Seek(offset int64, whence int) (int64, error)

Seek satisfies the io.Seeker interface.

func (*Caret) Write Uses

func (c *Caret) Write(s []byte) (n int, err error)

Write inserts s into the Frame's text at the Caret and increments the Caret.

func (*Caret) WriteByte Uses

func (c *Caret) WriteByte(x byte) error

WriteByte inserts x into the Frame's text at the Caret and increments the Caret.

func (*Caret) WriteRune Uses

func (c *Caret) WriteRune(r rune) (size int, err error)

WriteRune inserts r into the Frame's text at the Caret and increments the Caret.

func (*Caret) WriteString Uses

func (c *Caret) WriteString(s string) (n int, err error)

WriteString inserts s into the Frame's text at the Caret and increments the Caret.

type Direction Uses

type Direction bool

Direction is either forwards or backwards.

const (
    Forwards  Direction = false
    Backwards Direction = true
)

type Frame Uses

type Frame struct {
    // contains filtered or unexported fields
}

Frame holds Paragraphs of text.

The zero value is a valid Frame of empty text, which contains one Paragraph, which contains one Line, which contains one Box.

func (*Frame) FirstParagraph Uses

func (f *Frame) FirstParagraph() *Paragraph

FirstParagraph returns the first paragraph of this frame.

func (*Frame) Height Uses

func (f *Frame) Height() int

Height returns the height in pixels of this Frame.

func (*Frame) Len Uses

func (f *Frame) Len() int

Len returns the number of bytes in the Frame's text.

func (*Frame) LineCount Uses

func (f *Frame) LineCount() int

LineCount returns the number of Lines in this Frame.

This count includes any soft returns inserted to wrap text to the maxWidth.

func (*Frame) NewCaret Uses

func (f *Frame) NewCaret() *Caret

NewCaret returns a new Caret at the start of this Frame.

func (*Frame) ParagraphCount Uses

func (f *Frame) ParagraphCount() int

ParagraphCount returns the number of Paragraphs in this Frame.

This count excludes any soft returns inserted to wrap text to the maxWidth.

func (*Frame) SetFace Uses

func (f *Frame) SetFace(face font.Face)

SetFace sets the font face for measuring text.

func (*Frame) SetMaxWidth Uses

func (f *Frame) SetMaxWidth(m fixed.Int26_6)

SetMaxWidth sets the target maximum width of a Line of text, as a fixed-point fractional number of pixels. Text will be broken so that a Line's width is less than or equal to this maximum width. This line breaking is not strict. A Line containing asingleverylongword combined with a narrow maximum width will not be broken and will remain longer than the target maximum width; soft hyphens are not inserted.

A non-positive argument is treated as an infinite maximum width.

type Line Uses

type Line struct {
    // contains filtered or unexported fields
}

Line holds Boxes of text.

func (*Line) FirstBox Uses

func (l *Line) FirstBox(f *Frame) *Box

FirstBox returns the first Box of this Line.

f is the Frame that contains the Line.

func (*Line) Height Uses

func (l *Line) Height(f *Frame) int

Height returns the height in pixels of this Line.

func (*Line) Next Uses

func (l *Line) Next(f *Frame) *Line

Next returns the next Line after this one in the Paragraph.

f is the Frame that contains the Line.

type Paragraph Uses

type Paragraph struct {
    // contains filtered or unexported fields
}

Paragraph holds Lines of text.

func (*Paragraph) FirstLine Uses

func (p *Paragraph) FirstLine(f *Frame) *Line

FirstLine returns the first Line of this Paragraph.

f is the Frame that contains the Paragraph.

func (*Paragraph) Height Uses

func (p *Paragraph) Height(f *Frame) int

Height returns the height in pixels of this Paragraph.

func (*Paragraph) LineCount Uses

func (p *Paragraph) LineCount(f *Frame) int

LineCount returns the number of Lines in this Paragraph.

This count includes any soft returns inserted to wrap text to the maxWidth.

func (*Paragraph) Next Uses

func (p *Paragraph) Next(f *Frame) *Paragraph

Next returns the next Paragraph after this one in the Frame.

f is the Frame that contains the Paragraph.

Package text imports 7 packages (graph) and is imported by 1 packages. Updated 2017-06-03. Refresh now. Tools for package owners.